]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDCoupling/MEDCouplingUMesh.cxx
Salome HOME
Modification of C++ API of MEDCouplingMesh::getCellsContainingPoints to avoid copy.
[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 "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "InterpKernelAutoPtr.hxx"
37 #include "InterpKernelGeo2DNode.hxx"
38 #include "InterpKernelGeo2DEdgeLin.hxx"
39 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
40 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
41
42 #include <sstream>
43 #include <fstream>
44 #include <numeric>
45 #include <cstring>
46 #include <limits>
47 #include <list>
48
49 using namespace ParaMEDMEM;
50
51 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
52
53 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
54
55 MEDCouplingUMesh *MEDCouplingUMesh::New()
56 {
57   return new MEDCouplingUMesh;
58 }
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
61 {
62   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
63   ret->setName(meshName);
64   ret->setMeshDimension(meshDim);
65   return ret;
66 }
67
68 /*!
69  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
70  * between \a this and the new mesh.
71  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
72  *          delete this mesh using decrRef() as it is no more needed. 
73  */
74 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
75 {
76   return clone(true);
77 }
78
79 /*!
80  * Returns a new MEDCouplingMesh which is a copy of \a this one.
81  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
82  * this mesh are shared by the new mesh.
83  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
84  *          delete this mesh using decrRef() as it is no more needed. 
85  */
86 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
87 {
88   return new MEDCouplingUMesh(*this,recDeepCpy);
89 }
90
91 /*!
92  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
93  * The coordinates are shared between \a this and the returned instance.
94  * 
95  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
96  * \sa MEDCouplingUMesh::deepCpy
97  */
98 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception)
99 {
100   checkConnectivityFullyDefined();
101   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
103   ret->setConnectivity(c,ci);
104   return ret.retn();
105 }
106
107 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
108 {
109   if(!other)
110     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
111   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
112   if(!otherC)
113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
114   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
115   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
116 }
117
118 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
119 {
120   std::size_t ret=0;
121   if(_nodal_connec)
122     ret+=_nodal_connec->getHeapMemorySize();
123   if(_nodal_connec_index)
124     ret+=_nodal_connec_index->getHeapMemorySize();
125   return MEDCouplingPointSet::getHeapMemorySize()+ret;
126 }
127
128 void MEDCouplingUMesh::updateTime() const
129 {
130   MEDCouplingPointSet::updateTime();
131   if(_nodal_connec)
132     {
133       updateTimeWith(*_nodal_connec);
134     }
135   if(_nodal_connec_index)
136     {
137       updateTimeWith(*_nodal_connec_index);
138     }
139 }
140
141 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
142 {
143 }
144
145 /*!
146  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
147  * then \a this mesh is most probably is writable, exchangeable and available for most
148  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
149  * this method to check that all is in order with \a this mesh.
150  *  \throw If the mesh dimension is not set.
151  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
152  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
153  *  \throw If the connectivity data array has more than one component.
154  *  \throw If the connectivity data array has a named component.
155  *  \throw If the connectivity index data array has more than one component.
156  *  \throw If the connectivity index data array has a named component.
157  */
158 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
159 {
160   if(_mesh_dim<-1)
161    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
162   if(_mesh_dim!=-1)
163     MEDCouplingPointSet::checkCoherency();
164   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
165     {
166       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
167         {
168           std::ostringstream message;
169           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
170           throw INTERP_KERNEL::Exception(message.str().c_str());
171         }
172     }
173   if(_nodal_connec)
174     {
175       if(_nodal_connec->getNumberOfComponents()!=1)
176         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
177       if(_nodal_connec->getInfoOnComponent(0)!="")
178         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
179     }
180   else
181     if(_mesh_dim!=-1)
182       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
183   if(_nodal_connec_index)
184     {
185       if(_nodal_connec_index->getNumberOfComponents()!=1)
186         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
187       if(_nodal_connec_index->getInfoOnComponent(0)!="")
188         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
189     }
190   else
191     if(_mesh_dim!=-1)
192       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
193 }
194
195 /*!
196  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
197  * then \a this mesh is most probably is writable, exchangeable and available for all
198  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
199  * method thoroughly checks the nodal connectivity.
200  *  \param [in] eps - a not used parameter.
201  *  \throw If the mesh dimension is not set.
202  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
203  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
204  *  \throw If the connectivity data array has more than one component.
205  *  \throw If the connectivity data array has a named component.
206  *  \throw If the connectivity index data array has more than one component.
207  *  \throw If the connectivity index data array has a named component.
208  *  \throw If number of nodes defining an element does not correspond to the type of element.
209  *  \throw If the nodal connectivity includes an invalid node id.
210  */
211 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
212 {
213   checkCoherency();
214   if(_mesh_dim==-1)
215     return ;
216   int meshDim=getMeshDimension();
217   int nbOfNodes=getNumberOfNodes();
218   int nbOfCells=getNumberOfCells();
219   const int *ptr=_nodal_connec->getConstPointer();
220   const int *ptrI=_nodal_connec_index->getConstPointer();
221   for(int i=0;i<nbOfCells;i++)
222     {
223       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
224       if((int)cm.getDimension()!=meshDim)
225         {
226           std::ostringstream oss;
227           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
228           throw INTERP_KERNEL::Exception(oss.str().c_str());
229         }
230       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
231       if(!cm.isDynamic())
232         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
233           {
234             std::ostringstream oss;
235             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
236             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
237             throw INTERP_KERNEL::Exception(oss.str().c_str());
238           }
239       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
240         {
241           int nodeId=*w;
242           if(nodeId>=0)
243             {
244               if(nodeId>=nbOfNodes)
245                 {
246                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
247                   throw INTERP_KERNEL::Exception(oss.str().c_str());
248                 }
249             }
250           else if(nodeId<-1)
251             {
252               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
253               throw INTERP_KERNEL::Exception(oss.str().c_str());
254             }
255           else
256             {
257               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
258                 {
259                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
260                   throw INTERP_KERNEL::Exception(oss.str().c_str());
261                 }
262             }
263         }
264     }
265 }
266
267
268 /*!
269  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
270  * then \a this mesh is most probably is writable, exchangeable and available for all
271  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
272  *  \param [in] eps - a not used parameter.
273  *  \throw If the mesh dimension is not set.
274  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
275  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
276  *  \throw If the connectivity data array has more than one component.
277  *  \throw If the connectivity data array has a named component.
278  *  \throw If the connectivity index data array has more than one component.
279  *  \throw If the connectivity index data array has a named component.
280  *  \throw If number of nodes defining an element does not correspond to the type of element.
281  *  \throw If the nodal connectivity includes an invalid node id.
282  */
283 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
284 {
285   checkCoherency1(eps);
286 }
287
288 /*!
289  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
290  * elements contained in the mesh. For more info on the mesh dimension see
291  * \ref MEDCouplingUMeshPage.
292  *  \param [in] meshDim - a new mesh dimension.
293  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
294  */
295 void MEDCouplingUMesh::setMeshDimension(int meshDim)
296 {
297   if(meshDim<-1 || meshDim>3)
298     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
299   _mesh_dim=meshDim;
300   declareAsNew();
301 }
302
303 /*!
304  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
305  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
306  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
307  *
308  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
309  *
310  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
311  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
312  */
313 void MEDCouplingUMesh::allocateCells(int nbOfCells)
314 {
315   if(nbOfCells<0)
316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
317   if(_nodal_connec_index)
318     {
319       _nodal_connec_index->decrRef();
320     }
321   if(_nodal_connec)
322     {
323       _nodal_connec->decrRef();
324     }
325   _nodal_connec_index=DataArrayInt::New();
326   _nodal_connec_index->reserve(nbOfCells+1);
327   _nodal_connec_index->pushBackSilent(0);
328   _nodal_connec=DataArrayInt::New();
329   _nodal_connec->reserve(2*nbOfCells);
330   _types.clear();
331   declareAsNew();
332 }
333
334 /*!
335  * Appends a cell to the connectivity array. For deeper understanding what is
336  * happening see \ref MEDCouplingUMeshNodalConnectivity.
337  *  \param [in] type - type of cell to add.
338  *  \param [in] size - number of nodes constituting this cell.
339  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
340  * 
341  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
343  */
344 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
345 {
346   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
347   if(_nodal_connec_index==0)
348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
349   if((int)cm.getDimension()==_mesh_dim)
350     {
351       if(!cm.isDynamic())
352         if(size!=(int)cm.getNumberOfNodes())
353           {
354             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
355             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
356             throw INTERP_KERNEL::Exception(oss.str().c_str());
357           }
358       int idx=_nodal_connec_index->back();
359       int val=idx+size+1;
360       _nodal_connec_index->pushBackSilent(val);
361       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
362       _types.insert(type);
363     }
364   else
365     {
366       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
367       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
368       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
369       throw INTERP_KERNEL::Exception(oss.str().c_str());
370     }
371 }
372
373 /*!
374  * Compacts data arrays to release unused memory. This method is to be called after
375  * finishing cell insertion using \a this->insertNextCell().
376  * 
377  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
378  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
379  */
380 void MEDCouplingUMesh::finishInsertingCells()
381 {
382   _nodal_connec->pack();
383   _nodal_connec_index->pack();
384   _nodal_connec->declareAsNew();
385   _nodal_connec_index->declareAsNew();
386   updateTime();
387 }
388
389 /*!
390  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
391  * Useful for python users.
392  */
393 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
394 {
395   return new MEDCouplingUMeshCellIterator(this);
396 }
397
398 /*!
399  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
400  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
401  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
402  * Useful for python users.
403  */
404 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
405 {
406   if(!checkConsecutiveCellTypes())
407     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
408   return new MEDCouplingUMeshCellByTypeEntry(this);
409 }
410
411 /*!
412  * Returns a set of all cell types available in \a this mesh.
413  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
414  * \warning this method does not throw any exception even if \a this is not defined.
415  */
416 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
417 {
418   return _types;
419 }
420
421 /*!
422  * This method is a method that compares \a this and \a other.
423  * This method compares \b all attributes, even names and component names.
424  */
425 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
426 {
427   if(!other)
428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
429   std::ostringstream oss; oss.precision(15);
430   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
431   if(!otherC)
432     {
433       reason="mesh given in input is not castable in MEDCouplingUMesh !";
434       return false;
435     }
436   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
437     return false;
438   if(_mesh_dim!=otherC->_mesh_dim)
439     {
440       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
441       reason=oss.str();
442       return false;
443     }
444   if(_types!=otherC->_types)
445     {
446       oss << "umesh geometric type mismatch :\nThis geometric types are :";
447       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
448         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
449       oss << "\nOther geometric types are :";
450       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
451         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
452       reason=oss.str();
453       return false;
454     }
455   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
456     if(_nodal_connec==0 || otherC->_nodal_connec==0)
457       {
458         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
459         return false;
460       }
461   if(_nodal_connec!=otherC->_nodal_connec)
462     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
463       {
464         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
465         return false;
466       }
467   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
468     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
469       {
470         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
471         return false;
472       }
473   if(_nodal_connec_index!=otherC->_nodal_connec_index)
474     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
475       {
476         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
477         return false;
478       }
479   return true;
480 }
481
482 /*!
483  * Checks if data arrays of this mesh (node coordinates, nodal
484  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
485  * not considered.
486  *  \param [in] other - the mesh to compare with.
487  *  \param [in] prec - precision value used to compare node coordinates.
488  *  \return bool - \a true if the two meshes are same.
489  */
490 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
491 {
492   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
493   if(!otherC)
494     return false;
495   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
496     return false;
497   if(_mesh_dim!=otherC->_mesh_dim)
498     return false;
499   if(_types!=otherC->_types)
500     return false;
501   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
502     if(_nodal_connec==0 || otherC->_nodal_connec==0)
503       return false;
504   if(_nodal_connec!=otherC->_nodal_connec)
505     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
506       return false;
507   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
509       return false;
510   if(_nodal_connec_index!=otherC->_nodal_connec_index)
511     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
512       return false;
513   return true;
514 }
515
516 /*!
517  * Checks if \a this and \a other meshes are geometrically equivalent with high
518  * probability, else an exception is thrown. The meshes are considered equivalent if
519  * (1) meshes contain the same number of nodes and the same number of elements of the
520  * same types (2) three cells of the two meshes (first, last and middle) are based
521  * on coincident nodes (with a specified precision).
522  *  \param [in] other - the mesh to compare with.
523  *  \param [in] prec - the precision used to compare nodes of the two meshes.
524  *  \throw If the two meshes do not match.
525  */
526 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
527 {
528  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
529  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
530   if(!otherC)
531     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
532 }
533
534 /*!
535  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
536  * cells each node belongs to.
537  * \warning For speed reasons, this method does not check if node ids in the nodal
538  *          connectivity correspond to the size of node coordinates array.
539  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
540  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
541  *        dividing cell ids in \a revNodal into groups each referring to one
542  *        node. Its every element (except the last one) is an index pointing to the
543  *         first id of a group of cells. For example cells sharing the node #1 are 
544  *        described by following range of indices: 
545  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
546  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
547  *        Number of cells sharing the *i*-th node is
548  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
549  * \throw If the coordinates array is not set.
550  * \throw If the nodal connectivity of cells is not defined.
551  * 
552  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
553  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
554  */
555 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
556 {
557   checkFullyDefined();
558   int nbOfNodes=getNumberOfNodes();
559   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
560   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
561   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
562   const int *conn=_nodal_connec->getConstPointer();
563   const int *connIndex=_nodal_connec_index->getConstPointer();
564   int nbOfCells=getNumberOfCells();
565   int nbOfEltsInRevNodal=0;
566   for(int eltId=0;eltId<nbOfCells;eltId++)
567     {
568       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571         if(*iter>=0)//for polyhedrons
572           {
573             nbOfEltsInRevNodal++;
574             revNodalIndxPtr[(*iter)+1]++;
575           }
576     }
577   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
578   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
579   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
580   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
581   for(int eltId=0;eltId<nbOfCells;eltId++)
582     {
583       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
584       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
585       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
586         if(*iter>=0)//for polyhedrons
587           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
588     }
589 }
590
591 /// @cond INTERNAL
592
593 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
594 {
595   return id;
596 }
597
598 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
599 {
600   if(!compute)
601     return id+1;
602   else
603     {
604       if(cm.getOrientationStatus(nb,conn1,conn2))
605         return id+1;
606       else
607         return -(id+1);
608     }
609 }
610
611 class MinusOneSonsGenerator
612 {
613 public:
614   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
615   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
616   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
617   static const int DELTA=1;
618 private:
619   const INTERP_KERNEL::CellModel& _cm;
620 };
621
622 class MinusOneSonsGeneratorBiQuadratic
623 {
624 public:
625   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
626   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
627   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
628   static const int DELTA=1;
629 private:
630   const INTERP_KERNEL::CellModel& _cm;
631 };
632
633 class MinusTwoSonsGenerator
634 {
635 public:
636   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
637   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
638   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
639   static const int DELTA=2;
640 private:
641   const INTERP_KERNEL::CellModel& _cm;
642 };
643
644 /// @endcond
645
646 /*!
647  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
648  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
649  * describing correspondence between cells of \a this and the result meshes are
650  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
651  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
652  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
653  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
654  * \warning For speed reasons, this method does not check if node ids in the nodal
655  *          connectivity correspond to the size of node coordinates array.
656  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
657  *          to write this mesh to the MED file, its cells must be sorted using
658  *          sortCellsInMEDFileFrmt().
659  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
660  *         each cell of \a this mesh.
661  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
662  *        dividing cell ids in \a desc into groups each referring to one
663  *        cell of \a this mesh. Its every element (except the last one) is an index
664  *        pointing to the first id of a group of cells. For example cells of the
665  *        result mesh bounding the cell #1 of \a this mesh are described by following
666  *        range of indices:
667  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
668  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
669  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
670  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
671  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
672  *         by each cell of the result mesh.
673  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
674  *        in the result mesh,
675  *        dividing cell ids in \a revDesc into groups each referring to one
676  *        cell of the result mesh the same way as \a descIndx divides \a desc.
677  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
678  *        delete this mesh using decrRef() as it is no more needed.
679  *  \throw If the coordinates array is not set.
680  *  \throw If the nodal connectivity of cells is node defined.
681  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
682  *         revDescIndx == NULL.
683  * 
684  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
685  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
686  * \sa buildDescendingConnectivity2()
687  */
688 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
689 {
690   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
691 }
692
693 /*!
694  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
695  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
696  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
697  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
698  * \sa MEDCouplingUMesh::buildDescendingConnectivity
699  */
700 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
701 {
702   checkFullyDefined();
703   if(getMeshDimension()!=3)
704     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
705   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
706 }
707
708 /*!
709  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
710  * this->getMeshDimension(), that bound cells of \a this mesh. In
711  * addition arrays describing correspondence between cells of \a this and the result
712  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
713  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
714  *  mesh. This method differs from buildDescendingConnectivity() in that apart
715  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
716  * result meshes. So a positive id means that order of nodes in corresponding cells
717  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
718  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
719  * i.e. cell ids are one-based.
720  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
721  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
722  * \warning For speed reasons, this method does not check if node ids in the nodal
723  *          connectivity correspond to the size of node coordinates array.
724  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
725  *          to write this mesh to the MED file, its cells must be sorted using
726  *          sortCellsInMEDFileFrmt().
727  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
728  *         each cell of \a this mesh.
729  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
730  *        dividing cell ids in \a desc into groups each referring to one
731  *        cell of \a this mesh. Its every element (except the last one) is an index
732  *        pointing to the first id of a group of cells. For example cells of the
733  *        result mesh bounding the cell #1 of \a this mesh are described by following
734  *        range of indices:
735  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
736  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
737  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
738  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
739  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
740  *         by each cell of the result mesh.
741  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
742  *        in the result mesh,
743  *        dividing cell ids in \a revDesc into groups each referring to one
744  *        cell of the result mesh the same way as \a descIndx divides \a desc.
745  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
746  *        shares the node coordinates array with \a this mesh. The caller is to
747  *        delete this mesh using decrRef() as it is no more needed.
748  *  \throw If the coordinates array is not set.
749  *  \throw If the nodal connectivity of cells is node defined.
750  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
751  *         revDescIndx == NULL.
752  * 
753  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
754  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
755  * \sa buildDescendingConnectivity()
756  */
757 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
758 {
759   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
760 }
761
762 /*!
763  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
764  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
765  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
766  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
767  *
768  * \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
769  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
770  * \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.
771  */
772 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
773 {
774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
778   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
779   meshDM1=0;
780   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
781 }
782
783 /*!
784  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
785  * 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,
786  * excluding a set of meshdim-1 cells in input descending connectivity.
787  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
788  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
789  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
790  *
791  * \param [in] desc descending connectivity array.
792  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
793  * \param [in] revDesc reverse descending connectivity array.
794  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
795  * \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
796  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
797  * \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.
798  */
799 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
800                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
801 {
802   if(!desc || !descIndx || !revDesc || !revDescIndx)
803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
804   const int *descPtr=desc->getConstPointer();
805   const int *descIPtr=descIndx->getConstPointer();
806   const int *revDescPtr=revDesc->getConstPointer();
807   const int *revDescIPtr=revDescIndx->getConstPointer();
808   //
809   int nbCells=descIndx->getNumberOfTuples()-1;
810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
812   int *out1Ptr=out1->getPointer();
813   *out1Ptr++=0;
814   out0->reserve(desc->getNumberOfTuples());
815   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
816     {
817       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
818         {
819           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
820           s.erase(i);
821           out0->insertAtTheEnd(s.begin(),s.end());
822         }
823       *out1Ptr=out0->getNumberOfTuples();
824     }
825   neighbors=out0.retn();
826   neighborsIndx=out1.retn();
827 }
828
829 /// @cond INTERNAL
830
831 /*!
832  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
833  * For speed reasons no check of this will be done.
834  */
835 template<class SonsGenerator>
836 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
837 {
838   if(!desc || !descIndx || !revDesc || !revDescIndx)
839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
840   checkConnectivityFullyDefined();
841   int nbOfCells=getNumberOfCells();
842   int nbOfNodes=getNumberOfNodes();
843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
844   int *revNodalIndxPtr=revNodalIndx->getPointer();
845   const int *conn=_nodal_connec->getConstPointer();
846   const int *connIndex=_nodal_connec_index->getConstPointer();
847   std::string name="Mesh constituent of "; name+=getName();
848   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
849   ret->setCoords(getCoords());
850   ret->allocateCells(2*nbOfCells);
851   descIndx->alloc(nbOfCells+1,1);
852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
853   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
854   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
855     {
856       int pos=connIndex[eltId];
857       int posP1=connIndex[eltId+1];
858       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
859       SonsGenerator sg(cm);
860       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
861       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
862       for(unsigned i=0;i<nbOfSons;i++)
863         {
864           INTERP_KERNEL::NormalizedCellType cmsId;
865           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
866           for(unsigned k=0;k<nbOfNodesSon;k++)
867             if(tmp[k]>=0)
868               revNodalIndxPtr[tmp[k]+1]++;
869           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
870           revDesc2->pushBackSilent(eltId);
871         }
872       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
873     }
874   int nbOfCellsM1=ret->getNumberOfCells();
875   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
877   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
878   int *revNodalPtr=revNodal->getPointer();
879   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
880   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
881   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
882     {
883       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
884       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
885       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
886         if(*iter>=0)//for polyhedrons
887           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
888     }
889   //
890   DataArrayInt *commonCells=0,*commonCellsI=0;
891   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
893   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
894   int newNbOfCellsM1=-1;
895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
896                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
897   std::vector<bool> isImpacted(nbOfCellsM1,false);
898   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
899     for(int work2=work[0];work2!=work[1];work2++)
900       isImpacted[commonCellsPtr[work2]]=true;
901   const int *o2nM1Ptr=o2nM1->getConstPointer();
902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
903   const int *n2oM1Ptr=n2oM1->getConstPointer();
904   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
905   ret2->copyTinyInfoFrom(this);
906   desc->alloc(descIndx->back(),1);
907   int *descPtr=desc->getPointer();
908   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
909   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
910     {
911       if(!isImpacted[i])
912         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
913       else
914         {
915           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
916             {
917               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
918               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
919             }
920           else
921             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
922         }
923     }
924   revDesc->reserve(newNbOfCellsM1);
925   revDescIndx->alloc(newNbOfCellsM1+1,1);
926   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
927   const int *revDesc2Ptr=revDesc2->getConstPointer();
928   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
929     {
930       int oldCellIdM1=n2oM1Ptr[i];
931       if(!isImpacted[oldCellIdM1])
932         {
933           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
934           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
935         }
936       else
937         {
938           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
939             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
940           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
941           commonCellsIPtr++;
942         }
943     }
944   //
945   return ret2.retn();
946 }
947
948 struct MEDCouplingAccVisit
949 {
950   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
951   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
952   int _new_nb_of_nodes;
953 };
954
955 /// @endcond
956
957 /*!
958  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
959  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
960  * array of cell ids. Pay attention that after conversion all algorithms work slower
961  * with \a this mesh than before conversion. <br> If an exception is thrown during the
962  * conversion due presence of invalid ids in the array of cells to convert, as a
963  * result \a this mesh contains some already converted elements. In this case the 2D
964  * mesh remains valid but 3D mesh becomes \b inconsistent!
965  *  \warning This method can significantly modify the order of geometric types in \a this,
966  *          hence, to write this mesh to the MED file, its cells must be sorted using
967  *          sortCellsInMEDFileFrmt().
968  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
969  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
970  *         cellIdsToConvertBg.
971  *  \throw If the coordinates array is not set.
972  *  \throw If the nodal connectivity of cells is node defined.
973  *  \throw If dimension of \a this mesh is not either 2 or 3.
974  *
975  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
976  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
977  */
978 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
979 {
980   checkFullyDefined();
981   int dim=getMeshDimension();
982   if(dim<2 || dim>3)
983     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
984   int nbOfCells=getNumberOfCells();
985   if(dim==2)
986     {
987       const int *connIndex=_nodal_connec_index->getConstPointer();
988       int *conn=_nodal_connec->getPointer();
989       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
990         {
991           if(*iter>=0 && *iter<nbOfCells)
992             {
993               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
994               if(!cm.isQuadratic())
995                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
996               else
997                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
998             }
999           else
1000             {
1001               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1002               oss << " in range [0," << nbOfCells << ") !";
1003               throw INTERP_KERNEL::Exception(oss.str().c_str());
1004             }
1005         }
1006     }
1007   else
1008     {
1009       int *connIndex=_nodal_connec_index->getPointer();
1010       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1011       const int *connOld=_nodal_connec->getConstPointer();
1012       int connOldLgth=_nodal_connec->getNbOfElems();
1013       std::vector<int> connNew(connOld,connOld+connOldLgth);
1014       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1015         {
1016           if(*iter>=0 && *iter<nbOfCells)
1017             {
1018               int pos=connIndex[*iter];
1019               int posP1=connIndex[(*iter)+1];
1020               int lgthOld=posP1-pos-1;
1021               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1022               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1023               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1024               int *tmp=new int[nbOfFaces*lgthOld];
1025               int *work=tmp;
1026               for(int j=0;j<(int)nbOfFaces;j++)
1027                 {
1028                   INTERP_KERNEL::NormalizedCellType type;
1029                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1030                   work+=offset;
1031                   *work++=-1;
1032                 }
1033               std::size_t newLgth=std::distance(tmp,work)-1;
1034               std::size_t delta=newLgth-lgthOld;
1035               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1036               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1037               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1038               delete [] tmp;
1039             }
1040           else
1041             {
1042               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1043               oss << " in range [0," << nbOfCells << ") !";
1044               throw INTERP_KERNEL::Exception(oss.str().c_str());
1045             }
1046         }
1047       _nodal_connec->alloc((int)connNew.size(),1);
1048       int *newConnPtr=_nodal_connec->getPointer();
1049       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1050     }
1051   computeTypes();
1052 }
1053
1054 /*!
1055  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1056  * polyhedrons (if \a this is a 3D mesh).
1057  *  \warning As this method is purely for user-friendliness and no optimization is
1058  *          done to avoid construction of a useless vector, this method can be costly
1059  *          in memory.
1060  *  \throw If the coordinates array is not set.
1061  *  \throw If the nodal connectivity of cells is node defined.
1062  *  \throw If dimension of \a this mesh is not either 2 or 3.
1063  */
1064 void MEDCouplingUMesh::convertAllToPoly()
1065 {
1066   int nbOfCells=getNumberOfCells();
1067   std::vector<int> cellIds(nbOfCells);
1068   for(int i=0;i<nbOfCells;i++)
1069     cellIds[i]=i;
1070   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1071 }
1072
1073 /*!
1074  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1075  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1076  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1077  * base facet of the volume and the second half of nodes describes an opposite facet
1078  * having the same number of nodes as the base one. This method converts such
1079  * connectivity to a valid polyhedral format where connectivity of each facet is
1080  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1081  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1082  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1083  * a correct orientation of the first facet of a polyhedron, else orientation of a
1084  * corrected cell is reverse.<br>
1085  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1086  * it releases the user from boring description of polyhedra connectivity in the valid
1087  * format.
1088  *  \throw If \a this->getMeshDimension() != 3.
1089  *  \throw If \a this->getSpaceDimension() != 3.
1090  *  \throw If the nodal connectivity of cells is not defined.
1091  *  \throw If the coordinates array is not set.
1092  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1093  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1094  *
1095  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1096  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1097  */
1098 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1099 {
1100   checkFullyDefined();
1101   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1103   int nbOfCells=getNumberOfCells();
1104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1105   newCi->alloc(nbOfCells+1,1);
1106   int *newci=newCi->getPointer();
1107   const int *ci=_nodal_connec_index->getConstPointer();
1108   const int *c=_nodal_connec->getConstPointer();
1109   newci[0]=0;
1110   for(int i=0;i<nbOfCells;i++)
1111     {
1112       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1113       if(type==INTERP_KERNEL::NORM_POLYHED)
1114         {
1115           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1116             {
1117               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1118               throw INTERP_KERNEL::Exception(oss.str().c_str());
1119             }
1120           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1121           if(n2%2!=0)
1122             {
1123               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 !";
1124               throw INTERP_KERNEL::Exception(oss.str().c_str());
1125             }
1126           int n1=(int)(n2/2);
1127           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)
1128         }
1129       else
1130         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1131     }
1132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1133   newC->alloc(newci[nbOfCells],1);
1134   int *newc=newC->getPointer();
1135   for(int i=0;i<nbOfCells;i++)
1136     {
1137       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1138       if(type==INTERP_KERNEL::NORM_POLYHED)
1139         {
1140           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1141           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1142           *newc++=-1;
1143           for(std::size_t j=0;j<n1;j++)
1144             {
1145               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1146               newc[n1+5*j]=-1;
1147               newc[n1+5*j+1]=c[ci[i]+1+j];
1148               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1149               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1150               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1151             }
1152           newc+=n1*6;
1153         }
1154       else
1155         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1156     }
1157   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1158   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1159 }
1160
1161
1162 /*!
1163  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1164  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1165  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1166  *          to write this mesh to the MED file, its cells must be sorted using
1167  *          sortCellsInMEDFileFrmt().
1168  * \return \c true if at least one cell has been converted, \c false else. In the
1169  *         last case the nodal connectivity remains unchanged.
1170  * \throw If the coordinates array is not set.
1171  * \throw If the nodal connectivity of cells is not defined.
1172  * \throw If \a this->getMeshDimension() < 0.
1173  */
1174 bool MEDCouplingUMesh::unPolyze()
1175 {
1176   checkFullyDefined();
1177   int mdim=getMeshDimension();
1178   if(mdim<0)
1179     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1180   if(mdim<=1)
1181     return false;
1182   int nbOfCells=getNumberOfCells();
1183   if(nbOfCells<1)
1184     return false;
1185   int initMeshLgth=getMeshLength();
1186   int *conn=_nodal_connec->getPointer();
1187   int *index=_nodal_connec_index->getPointer();
1188   int posOfCurCell=0;
1189   int newPos=0;
1190   int lgthOfCurCell;
1191   bool ret=false;
1192   for(int i=0;i<nbOfCells;i++)
1193     {
1194       lgthOfCurCell=index[i+1]-posOfCurCell;
1195       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1196       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1197       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1198       int newLgth;
1199       if(cm.isDynamic())
1200         {
1201           switch(cm.getDimension())
1202             {
1203             case 2:
1204               {
1205                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1206                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1207                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1208                 break;
1209               }
1210             case 3:
1211               {
1212                 int nbOfFaces,lgthOfPolyhConn;
1213                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1214                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1215                 break;
1216               }
1217             case 1:
1218               {
1219                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1220                 break;
1221               }
1222             }
1223           ret=ret || (newType!=type);
1224           conn[newPos]=newType;
1225           newPos+=newLgth+1;
1226           posOfCurCell=index[i+1];
1227           index[i+1]=newPos;
1228         }
1229       else
1230         {
1231           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1232           newPos+=lgthOfCurCell;
1233           posOfCurCell+=lgthOfCurCell;
1234           index[i+1]=newPos;
1235         }
1236     }
1237   if(newPos!=initMeshLgth)
1238     _nodal_connec->reAlloc(newPos);
1239   if(ret)
1240     computeTypes();
1241   return ret;
1242 }
1243
1244 /*!
1245  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1246  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1247  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1248  *
1249  * \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 
1250  *             precision.
1251  */
1252 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1253 {
1254   checkFullyDefined();
1255   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1256     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1257   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1258   coords->recenterForMaxPrecision(eps);
1259   //
1260   int nbOfCells=getNumberOfCells();
1261   const int *conn=_nodal_connec->getConstPointer();
1262   const int *index=_nodal_connec_index->getConstPointer();
1263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1264   connINew->alloc(nbOfCells+1,1);
1265   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1267   bool changed=false;
1268   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1269     {
1270       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1271         {
1272           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1273           changed=true;
1274         }
1275       else
1276         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1277       *connINewPtr=connNew->getNumberOfTuples();
1278     }
1279   if(changed)
1280     setConnectivity(connNew,connINew,false);
1281 }
1282
1283 /*!
1284  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1285  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1286  * the format of returned DataArrayInt instance.
1287  * 
1288  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1289  * \sa MEDCouplingUMesh::getNodeIdsInUse
1290  */
1291 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1292 {
1293   checkConnectivityFullyDefined();
1294   int nbOfCells=getNumberOfCells();
1295   const int *connIndex=_nodal_connec_index->getConstPointer();
1296   const int *conn=_nodal_connec->getConstPointer();
1297   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1298   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1299   std::vector<bool> retS(maxElt,false);
1300   for(int i=0;i<nbOfCells;i++)
1301     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1302       if(conn[j]>=0)
1303         retS[conn[j]]=true;
1304   int sz=0;
1305   for(int i=0;i<maxElt;i++)
1306     if(retS[i])
1307       sz++;
1308   DataArrayInt *ret=DataArrayInt::New();
1309   ret->alloc(sz,1);
1310   int *retPtr=ret->getPointer();
1311   for(int i=0;i<maxElt;i++)
1312     if(retS[i])
1313       *retPtr++=i;
1314   return ret;
1315 }
1316
1317 /*!
1318  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1319  * \sa MEDCouplingUMesh::getNodeIdsInUse
1320  */
1321 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1322 {
1323   int nbOfNodes=(int)nodeIdsInUse.size();
1324   int nbOfCells=getNumberOfCells();
1325   const int *connIndex=_nodal_connec_index->getConstPointer();
1326   const int *conn=_nodal_connec->getConstPointer();
1327   for(int i=0;i<nbOfCells;i++)
1328     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1329       if(conn[j]>=0)
1330         {
1331           if(conn[j]<nbOfNodes)
1332             nodeIdsInUse[conn[j]]=true;
1333           else
1334             {
1335               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1336               throw INTERP_KERNEL::Exception(oss.str().c_str());
1337             }
1338         }
1339 }
1340
1341 /*!
1342  * Finds nodes not used in any cell and returns an array giving a new id to every node
1343  * by excluding the unused nodes, for which the array holds -1. The result array is
1344  * a mapping in "Old to New" mode. 
1345  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1346  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1347  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1348  *          if the node is unused or a new id else. The caller is to delete this
1349  *          array using decrRef() as it is no more needed.  
1350  *  \throw If the coordinates array is not set.
1351  *  \throw If the nodal connectivity of cells is not defined.
1352  *  \throw If the nodal connectivity includes an invalid id.
1353  *
1354  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1355  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1356  * \sa computeNodeIdsAlg()
1357  */
1358 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1359 {
1360   nbrOfNodesInUse=-1;
1361   int nbOfNodes=getNumberOfNodes();
1362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1363   ret->alloc(nbOfNodes,1);
1364   int *traducer=ret->getPointer();
1365   std::fill(traducer,traducer+nbOfNodes,-1);
1366   int nbOfCells=getNumberOfCells();
1367   const int *connIndex=_nodal_connec_index->getConstPointer();
1368   const int *conn=_nodal_connec->getConstPointer();
1369   for(int i=0;i<nbOfCells;i++)
1370     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1371       if(conn[j]>=0)
1372         {
1373           if(conn[j]<nbOfNodes)
1374             traducer[conn[j]]=1;
1375           else
1376             {
1377               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1378               throw INTERP_KERNEL::Exception(oss.str().c_str());
1379             }
1380         }
1381   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1382   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1383   return ret.retn();
1384 }
1385
1386 /*!
1387  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1388  * For each cell in \b this the number of nodes constituting cell is computed.
1389  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1390  * So for pohyhedrons some nodes can be counted several times in the returned result.
1391  * 
1392  * \return a newly allocated array
1393  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1394  */
1395 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1396 {
1397   checkConnectivityFullyDefined();
1398   int nbOfCells=getNumberOfCells();
1399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400   ret->alloc(nbOfCells,1);
1401   int *retPtr=ret->getPointer();
1402   const int *conn=getNodalConnectivity()->getConstPointer();
1403   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1404   for(int i=0;i<nbOfCells;i++,retPtr++)
1405     {
1406       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1407         *retPtr=connI[i+1]-connI[i]-1;
1408       else
1409         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1410     }
1411   return ret.retn();
1412 }
1413
1414 /*!
1415  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1416  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1417  *
1418  * \return DataArrayInt * - new object to be deallocated by the caller.
1419  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1420  */
1421 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1422 {
1423   checkConnectivityFullyDefined();
1424   int nbOfCells=getNumberOfCells();
1425   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1426   ret->alloc(nbOfCells,1);
1427   int *retPtr=ret->getPointer();
1428   const int *conn=getNodalConnectivity()->getConstPointer();
1429   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1430   for(int i=0;i<nbOfCells;i++,retPtr++)
1431     {
1432       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1433       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1434         *retPtr=(int)s.size();
1435       else
1436         {
1437           s.erase(-1);
1438           *retPtr=(int)s.size();
1439         }
1440     }
1441   return ret.retn();
1442 }
1443
1444 /*!
1445  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1446  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1447  * 
1448  * \return a newly allocated array
1449  */
1450 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1451 {
1452   checkConnectivityFullyDefined();
1453   int nbOfCells=getNumberOfCells();
1454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1455   ret->alloc(nbOfCells,1);
1456   int *retPtr=ret->getPointer();
1457   const int *conn=getNodalConnectivity()->getConstPointer();
1458   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1459   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1460     {
1461       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1462       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1463     }
1464   return ret.retn();
1465 }
1466
1467 /*!
1468  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1469  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1470  * array mean that the corresponding old node is no more used. 
1471  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1472  *           this->getNumberOfNodes() before call of this method. The caller is to
1473  *           delete this array using decrRef() as it is no more needed. 
1474  *  \throw If the coordinates array is not set.
1475  *  \throw If the nodal connectivity of cells is not defined.
1476  *  \throw If the nodal connectivity includes an invalid id.
1477  *
1478  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1479  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1480  */
1481 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1482 {
1483   return MEDCouplingPointSet::zipCoordsTraducer();
1484 }
1485
1486 /*!
1487  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1488  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1489  */
1490 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1491 {
1492   switch(compType)
1493     {
1494     case 0:
1495       return AreCellsEqual0(conn,connI,cell1,cell2);
1496     case 1:
1497       return AreCellsEqual1(conn,connI,cell1,cell2);
1498     case 2:
1499       return AreCellsEqual2(conn,connI,cell1,cell2);
1500     case 3:
1501       return AreCellsEqual3(conn,connI,cell1,cell2);
1502     case 7:
1503       return AreCellsEqual7(conn,connI,cell1,cell2);
1504     }
1505   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1506 }
1507
1508 /*!
1509  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1510  */
1511 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1512 {
1513   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1514     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1515   return 0;
1516 }
1517
1518 /*!
1519  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1520  */
1521 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1522 {
1523   int sz=connI[cell1+1]-connI[cell1];
1524   if(sz==connI[cell2+1]-connI[cell2])
1525     {
1526       if(conn[connI[cell1]]==conn[connI[cell2]])
1527         {
1528           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1529           unsigned dim=cm.getDimension();
1530           if(dim!=3)
1531             {
1532               if(dim!=1)
1533                 {
1534                   int sz1=2*(sz-1);
1535                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1536                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1537                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1538                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1539                   return work!=tmp+sz1?1:0;
1540                 }
1541               else
1542                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1543             }
1544           else
1545             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1546         }
1547     }
1548   return 0;
1549 }
1550
1551 /*!
1552  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1553  */
1554 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1555 {
1556   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1557     {
1558       if(conn[connI[cell1]]==conn[connI[cell2]])
1559         {
1560           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1561           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1562           return s1==s2?1:0;
1563         }
1564     }
1565   return 0;
1566 }
1567
1568 /*!
1569  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1570  */
1571 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1572 {
1573   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1574     {
1575       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1576       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1577       return s1==s2?1:0;
1578     }
1579   return 0;
1580 }
1581
1582 /*!
1583  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1584  */
1585 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1586 {
1587   int sz=connI[cell1+1]-connI[cell1];
1588   if(sz==connI[cell2+1]-connI[cell2])
1589     {
1590       if(conn[connI[cell1]]==conn[connI[cell2]])
1591         {
1592           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1593           unsigned dim=cm.getDimension();
1594           if(dim!=3)
1595             {
1596               if(dim!=1)
1597                 {
1598                   int sz1=2*(sz-1);
1599                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1600                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1601                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1602                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1603                   if(work!=tmp+sz1)
1604                     return 1;
1605                   else
1606                     {
1607                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1608                       std::reverse_iterator<int *> it2((int *)tmp);
1609                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1610                         return 2;
1611                       else
1612                         return 0;
1613                     }
1614                   
1615                   return work!=tmp+sz1?1:0;
1616                 }
1617               else
1618                 {//case of SEG2 and SEG3
1619                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1620                     return 1;
1621                   if(!cm.isQuadratic())
1622                     {
1623                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1624                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1625                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1626                         return 2;
1627                       return 0;
1628                     }
1629                   else
1630                     {
1631                       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])
1632                         return 2;
1633                       return 0;
1634                     }
1635                 }
1636             }
1637           else
1638             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1639         }
1640     }
1641   return 0;
1642 }
1643
1644 /*!
1645  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1646  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1647  * and result remains unchanged.
1648  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1649  * If in 'candidates' pool -1 value is considered as an empty value.
1650  * WARNING this method returns only ONE set of result !
1651  */
1652 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1653 {
1654   if(candidates.size()<1)
1655     return false;
1656   bool ret=false;
1657   std::vector<int>::const_iterator iter=candidates.begin();
1658   int start=(*iter++);
1659   for(;iter!=candidates.end();iter++)
1660     {
1661       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1662       if(status!=0)
1663         {
1664           if(!ret)
1665             {
1666               result->pushBackSilent(start);
1667               ret=true;
1668             }
1669           if(status==1)
1670             result->pushBackSilent(*iter);
1671           else
1672             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1673         }
1674     }
1675   return ret;
1676 }
1677
1678 /*!
1679  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1680  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1681  *
1682  * \param [in] compType input specifying the technique used to compare cells each other.
1683  *   - 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.
1684  *   - 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)
1685  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1686  *   - 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
1687  * can be used for users not sensitive to orientation of cell
1688  * \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.
1689  * \param [out] commonCells
1690  * \param [out] commonCellsI
1691  * \return the correspondance array old to new in a newly allocated array.
1692  * 
1693  */
1694 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1695 {
1696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1697   getReverseNodalConnectivity(revNodal,revNodalI);
1698   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1699 }
1700
1701 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1702                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1703 {
1704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1705   int nbOfCells=nodalI->getNumberOfTuples()-1;
1706   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1707   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1708   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1709   std::vector<bool> isFetched(nbOfCells,false);
1710   if(startCellId==0)
1711     {
1712       for(int i=0;i<nbOfCells;i++)
1713         {
1714           if(!isFetched[i])
1715             {
1716               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1717               std::vector<int> v,v2;
1718               if(connOfNode!=connPtr+connIPtr[i+1])
1719                 {
1720                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1721                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1722                   connOfNode++;
1723                 }
1724               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1725                 if(*connOfNode>=0)
1726                   {
1727                     v=v2;
1728                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1729                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1730                     v2.resize(std::distance(v2.begin(),it));
1731                   }
1732               if(v2.size()>1)
1733                 {
1734                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1735                     {
1736                       int pos=commonCellsI->back();
1737                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1738                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1739                         isFetched[*it]=true;
1740                     }
1741                 }
1742             }
1743         }
1744     }
1745   else
1746     {
1747       for(int i=startCellId;i<nbOfCells;i++)
1748         {
1749           if(!isFetched[i])
1750             {
1751               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1752               std::vector<int> v,v2;
1753               if(connOfNode!=connPtr+connIPtr[i+1])
1754                 {
1755                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1756                   connOfNode++;
1757                 }
1758               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1759                 if(*connOfNode>=0)
1760                   {
1761                     v=v2;
1762                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1763                     v2.resize(std::distance(v2.begin(),it));
1764                   }
1765               if(v2.size()>1)
1766                 {
1767                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1768                     {
1769                       int pos=commonCellsI->back();
1770                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1771                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1772                         isFetched[*it]=true;
1773                     }
1774                 }
1775             }
1776         }
1777     }
1778   commonCellsArr=commonCells.retn();
1779   commonCellsIArr=commonCellsI.retn();
1780 }
1781
1782 /*!
1783  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1784  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1785  * than \a other->getNumberOfCells() in the returned array means that there is no
1786  * corresponding cell in \a this mesh.
1787  * It is expected that \a this and \a other meshes share the same node coordinates
1788  * array, if it is not so an exception is thrown. 
1789  *  \param [in] other - the mesh to compare with.
1790  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1791  *         valid values [0,1,2], see zipConnectivityTraducer().
1792  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1793  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1794  *         values. The caller is to delete this array using
1795  *         decrRef() as it is no more needed.
1796  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1797  *         mesh.
1798  *
1799  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1800  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1801  *  \sa checkDeepEquivalOnSameNodesWith()
1802  *  \sa checkGeoEquivalWith()
1803  */
1804 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1805 {
1806   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1807   int nbOfCells=getNumberOfCells();
1808   static const int possibleCompType[]={0,1,2};
1809   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1810     {
1811       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1812       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1813       oss << " !";
1814       throw INTERP_KERNEL::Exception(oss.str().c_str());
1815     }
1816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1817   arr=o2n->substr(nbOfCells);
1818   arr->setName(other->getName().c_str());
1819   int tmp;
1820   if(other->getNumberOfCells()==0)
1821     return true;
1822   return arr->getMaxValue(tmp)<nbOfCells;
1823 }
1824
1825 /*!
1826  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1827  * This method tries to determine if \b other is fully included in \b this.
1828  * The main difference is that this method is not expected to throw exception.
1829  * This method has two outputs :
1830  *
1831  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1832  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1833  */
1834 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1835 {
1836   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1837   DataArrayInt *commonCells=0,*commonCellsI=0;
1838   int thisNbCells=getNumberOfCells();
1839   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1841   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1842   int otherNbCells=other->getNumberOfCells();
1843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1844   arr2->alloc(otherNbCells,1);
1845   arr2->fillWithZero();
1846   int *arr2Ptr=arr2->getPointer();
1847   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1848   for(int i=0;i<nbOfCommon;i++)
1849     {
1850       int start=commonCellsPtr[commonCellsIPtr[i]];
1851       if(start<thisNbCells)
1852         {
1853           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1854             {
1855               int sig=commonCellsPtr[j]>0?1:-1;
1856               int val=std::abs(commonCellsPtr[j])-1;
1857               if(val>=thisNbCells)
1858                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1859             }
1860         }
1861     }
1862   arr2->setName(other->getName().c_str());
1863   if(arr2->presenceOfValue(0))
1864     return false;
1865   arr=arr2.retn();
1866   return true;
1867 }
1868
1869 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1870 {
1871   if(!other)
1872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1873   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1874   if(!otherC)
1875     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1876   std::vector<const MEDCouplingUMesh *> ms(2);
1877   ms[0]=this;
1878   ms[1]=otherC;
1879   return MergeUMeshesOnSameCoords(ms);
1880 }
1881
1882 /*!
1883  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1884  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1885  * cellIds is not given explicitely but by a range python like.
1886  * 
1887  * \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.
1888  * \return a newly allocated
1889  * 
1890  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1891  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1892  */
1893 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1894 {
1895   if(getMeshDimension()!=-1)
1896     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1897   else
1898     {
1899       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1900       if(newNbOfCells!=1)
1901         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1902       if(start!=0)
1903         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1904       incrRef();
1905       return const_cast<MEDCouplingUMesh *>(this);
1906     }
1907 }
1908
1909 /*!
1910  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1911  * The result mesh shares or not the node coordinates array with \a this mesh depending
1912  * on \a keepCoords parameter.
1913  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1914  *           to write this mesh to the MED file, its cells must be sorted using
1915  *           sortCellsInMEDFileFrmt().
1916  *  \param [in] begin - an array of cell ids to include to the new mesh.
1917  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1918  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1919  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1920  *         by calling zipCoords().
1921  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1922  *         to delete this mesh using decrRef() as it is no more needed. 
1923  *  \throw If the coordinates array is not set.
1924  *  \throw If the nodal connectivity of cells is not defined.
1925  *  \throw If any cell id in the array \a begin is not valid.
1926  *
1927  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1928  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1929  */
1930 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1931 {
1932   if(getMeshDimension()!=-1)
1933     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1934   else
1935     {
1936       if(end-begin!=1)
1937         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1938       if(begin[0]!=0)
1939         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1940       incrRef();
1941       return const_cast<MEDCouplingUMesh *>(this);
1942     }
1943 }
1944
1945 /*!
1946  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1947  *
1948  * 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.
1949  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1950  * The number of cells of \b this will remain the same with this method.
1951  *
1952  * \param [in] begin begin of cell ids (included) of cells in this to assign
1953  * \param [in] end end of cell ids (excluded) of cells in this to assign
1954  * \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 ).
1955  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1956  */
1957 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1958 {
1959   checkConnectivityFullyDefined();
1960   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1961   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1963   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1964     {
1965       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1966       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1967       throw INTERP_KERNEL::Exception(oss.str().c_str());
1968     }
1969   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1970   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1971     {
1972       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1973       throw INTERP_KERNEL::Exception(oss.str().c_str());
1974     }
1975   int nbOfCells=getNumberOfCells();
1976   bool easyAssign=true;
1977   const int *connI=_nodal_connec_index->getConstPointer();
1978   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1979   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1980     {
1981       if(*it>=0 && *it<nbOfCells)
1982         {
1983           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1984         }
1985       else
1986         {
1987           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1988           throw INTERP_KERNEL::Exception(oss.str().c_str());
1989         }
1990     }
1991   if(easyAssign)
1992     {
1993       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1994       computeTypes();
1995     }
1996   else
1997     {
1998       DataArrayInt *arrOut=0,*arrIOut=0;
1999       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2000                                                arrOut,arrIOut);
2001       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2002       setConnectivity(arrOut,arrIOut,true);
2003     }
2004 }
2005
2006 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2007 {
2008   checkConnectivityFullyDefined();
2009   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2010   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2012   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2013     {
2014       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2015       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2016       throw INTERP_KERNEL::Exception(oss.str().c_str());
2017     }
2018   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2019   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2020     {
2021       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2022       throw INTERP_KERNEL::Exception(oss.str().c_str());
2023     }
2024   int nbOfCells=getNumberOfCells();
2025   bool easyAssign=true;
2026   const int *connI=_nodal_connec_index->getConstPointer();
2027   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2028   int it=start;
2029   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2030     {
2031       if(it>=0 && it<nbOfCells)
2032         {
2033           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2034         }
2035       else
2036         {
2037           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2038           throw INTERP_KERNEL::Exception(oss.str().c_str());
2039         }
2040     }
2041   if(easyAssign)
2042     {
2043       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2044       computeTypes();
2045     }
2046   else
2047     {
2048       DataArrayInt *arrOut=0,*arrIOut=0;
2049       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2050                                                 arrOut,arrIOut);
2051       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2052       setConnectivity(arrOut,arrIOut,true);
2053     }
2054 }                      
2055
2056 /*!
2057  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2058  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2059  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2060  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2061  *
2062  * \param [in] begin input start of array of node ids.
2063  * \param [in] end input end of array of node ids.
2064  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2065  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2066  */
2067 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2068 {
2069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2070   checkConnectivityFullyDefined();
2071   int tmp=-1;
2072   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2073   std::vector<bool> fastFinder(sz,false);
2074   for(const int *work=begin;work!=end;work++)
2075     if(*work>=0 && *work<sz)
2076       fastFinder[*work]=true;
2077   int nbOfCells=getNumberOfCells();
2078   const int *conn=getNodalConnectivity()->getConstPointer();
2079   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2080   for(int i=0;i<nbOfCells;i++)
2081     {
2082       int ref=0,nbOfHit=0;
2083       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2084         if(*work2>=0)
2085           {
2086             ref++;
2087             if(fastFinder[*work2])
2088               nbOfHit++;
2089           }
2090       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2091         cellIdsKept->pushBackSilent(i);
2092     }
2093   cellIdsKeptArr=cellIdsKept.retn();
2094 }
2095
2096 /*!
2097  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2098  * this->getMeshDimension(), that bound some cells of \a this mesh.
2099  * The cells of lower dimension to include to the result mesh are selected basing on
2100  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2101  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2102  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2103  * created mesh shares the node coordinates array with \a this mesh. 
2104  *  \param [in] begin - the array of node ids.
2105  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2106  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2107  *         array \a begin are added, else cells whose any node is in the
2108  *         array \a begin are added.
2109  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2110  *         to delete this mesh using decrRef() as it is no more needed. 
2111  *  \throw If the coordinates array is not set.
2112  *  \throw If the nodal connectivity of cells is not defined.
2113  *  \throw If any node id in \a begin is not valid.
2114  *
2115  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2116  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2117  */
2118 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2119 {
2120   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2121   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2122   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2123   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2124   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2125 }
2126
2127 /*!
2128  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2129  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2130  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2131  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2132  *         by calling zipCoords().
2133  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2134  *         to delete this mesh using decrRef() as it is no more needed. 
2135  *  \throw If the coordinates array is not set.
2136  *  \throw If the nodal connectivity of cells is not defined.
2137  *
2138  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2139  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2140  */
2141 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2142 {
2143   DataArrayInt *desc=DataArrayInt::New();
2144   DataArrayInt *descIndx=DataArrayInt::New();
2145   DataArrayInt *revDesc=DataArrayInt::New();
2146   DataArrayInt *revDescIndx=DataArrayInt::New();
2147   //
2148   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2149   revDesc->decrRef();
2150   desc->decrRef();
2151   descIndx->decrRef();
2152   int nbOfCells=meshDM1->getNumberOfCells();
2153   const int *revDescIndxC=revDescIndx->getConstPointer();
2154   std::vector<int> boundaryCells;
2155   for(int i=0;i<nbOfCells;i++)
2156     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2157       boundaryCells.push_back(i);
2158   revDescIndx->decrRef();
2159   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2160   return ret;
2161 }
2162
2163 /*!
2164  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2165  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2166  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2167  */
2168 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2169 {
2170   checkFullyDefined();
2171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2175   //
2176   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2177   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2178   //
2179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2181   const int *revDescPtr=revDesc->getConstPointer();
2182   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2183   int nbOfCells=getNumberOfCells();
2184   std::vector<bool> ret1(nbOfCells,false);
2185   int sz=0;
2186   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2187     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2188       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2189   //
2190   DataArrayInt *ret2=DataArrayInt::New();
2191   ret2->alloc(sz,1);
2192   int *ret2Ptr=ret2->getPointer();
2193   sz=0;
2194   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2195     if(*it)
2196       *ret2Ptr++=sz;
2197   ret2->setName("BoundaryCells");
2198   return ret2;
2199 }
2200
2201 /*!
2202  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2203  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2204  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2205  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2206  *
2207  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2208  * This method method returns cells ids set s = s1 + s2 where :
2209  * 
2210  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2211  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2212  *
2213  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2214  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2215  *
2216  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2217  * \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
2218  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2219  */
2220 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2221 {
2222   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2223     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2224   checkConnectivityFullyDefined();
2225   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2226   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2227     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2228   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2230   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2232   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2233   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2234   DataArrayInt *idsOtherInConsti=0;
2235   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2237   if(!b)
2238     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2239   std::set<int> s1;
2240   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2241     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2244   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2245   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2247   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2248   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2249   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2250   neighThisPartAuto=0;
2251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2252   const int li[2]={0,1};
2253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2254   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2256   s_renum1->sort();
2257   //
2258   cellIdsRk0=s0arr.retn();
2259   cellIdsRk1=s_renum1.retn();
2260 }
2261
2262 /*!
2263  * 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
2264  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2265  * 
2266  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2267  */
2268 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2269 {
2270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2274   //
2275   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2276   revDesc=0; desc=0; descIndx=0;
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2279   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2280 }
2281
2282 /*!
2283  * Finds nodes lying on the boundary of \a this mesh.
2284  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2285  *          nodes. The caller is to delete this array using decrRef() as it is no
2286  *          more needed.
2287  *  \throw If the coordinates array is not set.
2288  *  \throw If the nodal connectivity of cells is node defined.
2289  *
2290  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2291  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2292  */
2293 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2294 {
2295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2296   return skin->computeFetchedNodeIds();
2297 }
2298
2299 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2300 {
2301   incrRef();
2302   return const_cast<MEDCouplingUMesh *>(this);
2303 }
2304
2305 /*!
2306  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2307  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2308  * 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.
2309  * 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.
2310  * 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.
2311  *
2312  * \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
2313  *             parameter is altered during the call.
2314  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2315  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2316  * \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.
2317  *
2318  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2319  */
2320 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2321                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2322 {
2323   checkFullyDefined();
2324   otherDimM1OnSameCoords.checkFullyDefined();
2325   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2326     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2327   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2328     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2329   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2330   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2333   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2334   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2338   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2339   //
2340   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2342   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2343   DataArrayInt *idsTmp=0;
2344   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2346   if(!b)
2347     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2348   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2349   DataArrayInt *tmp0=0,*tmp1=0;
2350   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2355   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2356   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2357   //
2358   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2359   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2360   nodeIdsToDuplicate=s3.retn();
2361 }
2362
2363 /*!
2364  * This method operates a modification of the connectivity and coords in \b this.
2365  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2366  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2367  * 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
2368  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2369  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2370  * 
2371  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2372  * 
2373  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2374  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2375  */
2376 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2377 {
2378   int nbOfNodes=getNumberOfNodes();
2379   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2380   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2381 }
2382
2383 /*!
2384  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2385  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2386  * This method is a generalization of shiftNodeNumbersInConn().
2387  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2388  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2389  *         this->getNumberOfNodes(), in "Old to New" mode. 
2390  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2391  *  \throw If the nodal connectivity of cells is not defined.
2392  *
2393  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2394  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2395  */
2396 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2397 {
2398   checkConnectivityFullyDefined();
2399   int *conn=getNodalConnectivity()->getPointer();
2400   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2401   int nbOfCells=getNumberOfCells();
2402   for(int i=0;i<nbOfCells;i++)
2403     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2404       {
2405         int& node=conn[iconn];
2406         if(node>=0)//avoid polyhedron separator
2407           {
2408             node=newNodeNumbersO2N[node];
2409           }
2410       }
2411   _nodal_connec->declareAsNew();
2412   updateTime();
2413 }
2414
2415 /*!
2416  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2417  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2418  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2419  * 
2420  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2421  */
2422 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2423 {
2424   checkConnectivityFullyDefined();
2425   int *conn=getNodalConnectivity()->getPointer();
2426   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2427   int nbOfCells=getNumberOfCells();
2428   for(int i=0;i<nbOfCells;i++)
2429     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2430       {
2431         int& node=conn[iconn];
2432         if(node>=0)//avoid polyhedron separator
2433           {
2434             node+=delta;
2435           }
2436       }
2437   _nodal_connec->declareAsNew();
2438   updateTime();
2439 }
2440
2441 /*!
2442  * This method operates a modification of the connectivity in \b this.
2443  * 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.
2444  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2445  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2446  * 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
2447  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2448  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2449  * 
2450  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2451  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2452  * 
2453  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2454  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2455  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2456  */
2457 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2458 {
2459   checkConnectivityFullyDefined();
2460   std::map<int,int> m;
2461   int val=offset;
2462   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2463     m[*work]=val;
2464   int *conn=getNodalConnectivity()->getPointer();
2465   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2466   int nbOfCells=getNumberOfCells();
2467   for(int i=0;i<nbOfCells;i++)
2468     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2469       {
2470         int& node=conn[iconn];
2471         if(node>=0)//avoid polyhedron separator
2472           {
2473             std::map<int,int>::iterator it=m.find(node);
2474             if(it!=m.end())
2475               node=(*it).second;
2476           }
2477       }
2478   updateTime();
2479 }
2480
2481 /*!
2482  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2483  *
2484  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2485  * After the call of this method the number of cells remains the same as before.
2486  *
2487  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2488  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2489  * be strictly in [0;this->getNumberOfCells()).
2490  *
2491  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2492  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2493  * should be contained in[0;this->getNumberOfCells()).
2494  * 
2495  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2496  */
2497 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2498 {
2499   checkConnectivityFullyDefined();
2500   int nbCells=getNumberOfCells();
2501   const int *array=old2NewBg;
2502   if(check)
2503     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2504   //
2505   const int *conn=_nodal_connec->getConstPointer();
2506   const int *connI=_nodal_connec_index->getConstPointer();
2507   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2509   const int *n2oPtr=n2o->begin();
2510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2511   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2512   newConn->copyStringInfoFrom(*_nodal_connec);
2513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2514   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2515   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2516   //
2517   int *newC=newConn->getPointer();
2518   int *newCI=newConnI->getPointer();
2519   int loc=0;
2520   newCI[0]=loc;
2521   for(int i=0;i<nbCells;i++)
2522     {
2523       int pos=n2oPtr[i];
2524       int nbOfElts=connI[pos+1]-connI[pos];
2525       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2526       loc+=nbOfElts;
2527       newCI[i+1]=loc;
2528     }
2529   //
2530   setConnectivity(newConn,newConnI);
2531   if(check)
2532     free(const_cast<int *>(array));
2533 }
2534
2535 /*!
2536  * Finds cells whose bounding boxes intersect a given bounding box.
2537  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2538  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2539  *         zMax (if in 3D). 
2540  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2541  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2542  *         extent of the bounding box of cell to produce an addition to this bounding box.
2543  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2544  *         cells. The caller is to delete this array using decrRef() as it is no more
2545  *         needed. 
2546  *  \throw If the coordinates array is not set.
2547  *  \throw If the nodal connectivity of cells is not defined.
2548  *
2549  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2550  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2551  */
2552 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2553 {
2554   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2555   if(getMeshDimension()==-1)
2556     {
2557       elems->pushBackSilent(0);
2558       return elems.retn();
2559     }
2560   int dim=getSpaceDimension();
2561   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2562   const int* conn      = getNodalConnectivity()->getConstPointer();
2563   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2564   const double* coords = getCoords()->getConstPointer();
2565   int nbOfCells=getNumberOfCells();
2566   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2567     {
2568       for (int i=0; i<dim; i++)
2569         {
2570           elem_bb[i*2]=std::numeric_limits<double>::max();
2571           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2572         }
2573
2574       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2575         {
2576           int node= conn[inode];
2577           if(node>=0)//avoid polyhedron separator
2578             {
2579               for (int idim=0; idim<dim; idim++)
2580                 {
2581                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2582                     {
2583                       elem_bb[idim*2] = coords[node*dim+idim] ;
2584                     }
2585                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2586                     {
2587                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2588                     }
2589                 }
2590             }
2591         }
2592       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2593         elems->pushBackSilent(ielem);
2594     }
2595   return elems.retn();
2596 }
2597
2598 /*!
2599  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2600  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2601  * added in 'elems' parameter.
2602  */
2603 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2604 {
2605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2606   if(getMeshDimension()==-1)
2607     {
2608       elems->pushBackSilent(0);
2609       return elems.retn();
2610     }
2611   int dim=getSpaceDimension();
2612   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2613   const int* conn      = getNodalConnectivity()->getConstPointer();
2614   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2615   const double* coords = getCoords()->getConstPointer();
2616   int nbOfCells=getNumberOfCells();
2617   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2618     {
2619       for (int i=0; i<dim; i++)
2620         {
2621           elem_bb[i*2]=std::numeric_limits<double>::max();
2622           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2623         }
2624
2625       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2626         {
2627           int node= conn[inode];
2628           if(node>=0)//avoid polyhedron separator
2629             {
2630               for (int idim=0; idim<dim; idim++)
2631                 {
2632                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2633                     {
2634                       elem_bb[idim*2] = coords[node*dim+idim] ;
2635                     }
2636                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2637                     {
2638                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2639                     }
2640                 }
2641             }
2642         }
2643       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2644         elems->pushBackSilent(ielem);
2645     }
2646   return elems.retn();
2647 }
2648
2649 /*!
2650  * Returns a type of a cell by its id.
2651  *  \param [in] cellId - the id of the cell of interest.
2652  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2653  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2654  */
2655 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2656 {
2657   const int *ptI=_nodal_connec_index->getConstPointer();
2658   const int *pt=_nodal_connec->getConstPointer();
2659   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2660     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2661   else
2662     {
2663       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2664       throw INTERP_KERNEL::Exception(oss.str().c_str());
2665     }
2666 }
2667
2668 /*!
2669  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2670  * This method does not throw exception if geometric type \a type is not in \a this.
2671  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2672  * The coordinates array is not considered here.
2673  *
2674  * \param [in] type the geometric type
2675  * \return cell ids in this having geometric type \a type.
2676  */
2677 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2678 {
2679   
2680   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2681   ret->alloc(0,1);
2682   checkConnectivityFullyDefined();
2683   int nbCells=getNumberOfCells();
2684   int mdim=getMeshDimension();
2685   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2686   if(mdim!=(int)cm.getDimension())
2687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2688   const int *ptI=_nodal_connec_index->getConstPointer();
2689   const int *pt=_nodal_connec->getConstPointer();
2690   for(int i=0;i<nbCells;i++)
2691     {
2692       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2693         ret->pushBackSilent(i);
2694     }
2695   return ret.retn();
2696 }
2697
2698 /*!
2699  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2700  */
2701 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2702 {
2703   const int *ptI=_nodal_connec_index->getConstPointer();
2704   const int *pt=_nodal_connec->getConstPointer();
2705   int nbOfCells=getNumberOfCells();
2706   int ret=0;
2707   for(int i=0;i<nbOfCells;i++)
2708     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2709       ret++;
2710   return ret;
2711 }
2712
2713 /*!
2714  * Returns the nodal connectivity of a given cell.
2715  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2716  * all returned node ids can be used in getCoordinatesOfNode().
2717  *  \param [in] cellId - an id of the cell of interest.
2718  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2719  *         cleared before the appending.
2720  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2721  */
2722 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2723 {
2724   const int *ptI=_nodal_connec_index->getConstPointer();
2725   const int *pt=_nodal_connec->getConstPointer();
2726   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2727     if(*w>=0)
2728       conn.push_back(*w);
2729 }
2730
2731 std::string MEDCouplingUMesh::simpleRepr() const
2732 {
2733   static const char msg0[]="No coordinates specified !";
2734   std::ostringstream ret;
2735   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2736   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2737   int tmpp1,tmpp2;
2738   double tt=getTime(tmpp1,tmpp2);
2739   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2740   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2741   if(_mesh_dim>=-1)
2742     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2743   else
2744     { ret << " Mesh dimension has not been set or is invalid !"; }
2745   if(_coords!=0)
2746     {
2747       const int spaceDim=getSpaceDimension();
2748       ret << spaceDim << "\nInfo attached on space dimension : ";
2749       for(int i=0;i<spaceDim;i++)
2750         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2751       ret << "\n";
2752     }
2753   else
2754     ret << msg0 << "\n";
2755   ret << "Number of nodes : ";
2756   if(_coords!=0)
2757     ret << getNumberOfNodes() << "\n";
2758   else
2759     ret << msg0 << "\n";
2760   ret << "Number of cells : ";
2761   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2762     ret << getNumberOfCells() << "\n";
2763   else
2764     ret << "No connectivity specified !" << "\n";
2765   ret << "Cell types present : ";
2766   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2767     {
2768       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2769       ret << cm.getRepr() << " ";
2770     }
2771   ret << "\n";
2772   return ret.str();
2773 }
2774
2775 std::string MEDCouplingUMesh::advancedRepr() const
2776 {
2777   std::ostringstream ret;
2778   ret << simpleRepr();
2779   ret << "\nCoordinates array : \n___________________\n\n";
2780   if(_coords)
2781     _coords->reprWithoutNameStream(ret);
2782   else
2783     ret << "No array set !\n";
2784   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2785   reprConnectivityOfThisLL(ret);
2786   return ret.str();
2787 }
2788
2789 /*!
2790  * This method returns a C++ code that is a dump of \a this.
2791  * This method will throw if this is not fully defined.
2792  */
2793 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2794 {
2795   static const char coordsName[]="coords";
2796   static const char connName[]="conn";
2797   static const char connIName[]="connI";
2798   checkFullyDefined();
2799   std::ostringstream ret; ret << "// coordinates" << std::endl;
2800   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2801   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2802   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2803   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2804   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2805   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2806   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2807   return ret.str();
2808 }
2809
2810 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2811 {
2812   std::ostringstream ret;
2813   reprConnectivityOfThisLL(ret);
2814   return ret.str();
2815 }
2816
2817 /*!
2818  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2819  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2820  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2821  * some algos).
2822  * 
2823  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2824  * 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
2825  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2826  */
2827 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2828 {
2829   int mdim=getMeshDimension();
2830   if(mdim<0)
2831     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2832   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2834   bool needToCpyCT=true;
2835   if(!_nodal_connec)
2836     {
2837       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2838       needToCpyCT=false;
2839     }
2840   else
2841     {
2842       tmp1=_nodal_connec;
2843       tmp1->incrRef();
2844     }
2845   if(!_nodal_connec_index)
2846     {
2847       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2848       needToCpyCT=false;
2849     }
2850   else
2851     {
2852       tmp2=_nodal_connec_index;
2853       tmp2->incrRef();
2854     }
2855   ret->setConnectivity(tmp1,tmp2,false);
2856   if(needToCpyCT)
2857     ret->_types=_types;
2858   if(!_coords)
2859     {
2860       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2861       ret->setCoords(coords);
2862     }
2863   else
2864     ret->setCoords(_coords);
2865   return ret.retn();
2866 }
2867
2868 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2869 {
2870   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2871     {
2872       int nbOfCells=getNumberOfCells();
2873       const int *c=_nodal_connec->getConstPointer();
2874       const int *ci=_nodal_connec_index->getConstPointer();
2875       for(int i=0;i<nbOfCells;i++)
2876         {
2877           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2878           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2879           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2880           stream << "\n";
2881         }
2882     }
2883   else
2884     stream << "Connectivity not defined !\n";
2885 }
2886
2887 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2888 {
2889   const int *ptI=_nodal_connec_index->getConstPointer();
2890   const int *pt=_nodal_connec->getConstPointer();
2891   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2892     return ptI[cellId+1]-ptI[cellId]-1;
2893   else
2894     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2895 }
2896
2897 /*!
2898  * Returns types of cells of the specified part of \a this mesh.
2899  * This method avoids computing sub-mesh explicitely to get its types.
2900  *  \param [in] begin - an array of cell ids of interest.
2901  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2902  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2903  *         describing the cell types. 
2904  *  \throw If the coordinates array is not set.
2905  *  \throw If the nodal connectivity of cells is not defined.
2906  *  \sa getAllTypes()
2907  */
2908 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2909 {
2910   checkFullyDefined();
2911   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2912   const int *conn=_nodal_connec->getConstPointer();
2913   const int *connIndex=_nodal_connec_index->getConstPointer();
2914   for(const int *w=begin;w!=end;w++)
2915     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2916   return ret;
2917 }
2918
2919 /*!
2920  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2921  * a set of types of cells constituting \a this mesh. 
2922  * This method is for advanced users having prepared their connectivity before. For
2923  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2924  *  \param [in] conn - the nodal connectivity array. 
2925  *  \param [in] connIndex - the nodal connectivity index array.
2926  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2927  *         mesh is updated.
2928  */
2929 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2930 {
2931   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2932   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2933   if(isComputingTypes)
2934     computeTypes();
2935   declareAsNew();
2936 }
2937
2938 /*!
2939  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2940  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2941  */
2942 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2943                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2944                                                                                 _types(other._types)
2945 {
2946   if(other._nodal_connec)
2947     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2948   if(other._nodal_connec_index)
2949     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2950 }
2951
2952 MEDCouplingUMesh::~MEDCouplingUMesh()
2953 {
2954   if(_nodal_connec)
2955     _nodal_connec->decrRef();
2956   if(_nodal_connec_index)
2957     _nodal_connec_index->decrRef();
2958 }
2959
2960 /*!
2961  * Recomputes a set of cell types of \a this mesh. For more info see
2962  * \ref MEDCouplingUMeshNodalConnectivity.
2963  */
2964 void MEDCouplingUMesh::computeTypes()
2965 {
2966   if(_nodal_connec && _nodal_connec_index)
2967     {
2968       _types.clear();
2969       const int *conn=_nodal_connec->getConstPointer();
2970       const int *connIndex=_nodal_connec_index->getConstPointer();
2971       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2972       if (nbOfElem > 0)
2973         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2974           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2975     }
2976 }
2977
2978 /*!
2979  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2980  */
2981 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2982 {
2983   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2984     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2985 }
2986
2987 /*!
2988  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2989  */
2990 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2991 {
2992   if(!_nodal_connec_index || !_nodal_connec)
2993     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2994 }
2995
2996 /*!
2997  * Returns a number of cells constituting \a this mesh. 
2998  *  \return int - the number of cells in \a this mesh.
2999  *  \throw If the nodal connectivity of cells is not defined.
3000  */
3001 int MEDCouplingUMesh::getNumberOfCells() const
3002
3003   if(_nodal_connec_index)
3004     return _nodal_connec_index->getNumberOfTuples()-1;
3005   else
3006     if(_mesh_dim==-1)
3007       return 1;
3008     else
3009       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3010 }
3011
3012 /*!
3013  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3014  * mesh. For more info see \ref MEDCouplingMeshesPage.
3015  *  \return int - the dimension of \a this mesh.
3016  *  \throw If the mesh dimension is not defined using setMeshDimension().
3017  */
3018 int MEDCouplingUMesh::getMeshDimension() const
3019 {
3020   if(_mesh_dim<-1)
3021     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3022   return _mesh_dim;
3023 }
3024
3025 /*!
3026  * Returns a length of the nodal connectivity array.
3027  * This method is for test reason. Normally the integer returned is not useable by
3028  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3029  *  \return int - the length of the nodal connectivity array.
3030  */
3031 int MEDCouplingUMesh::getMeshLength() const
3032 {
3033   return _nodal_connec->getNbOfElems();
3034 }
3035
3036 /*!
3037  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3038  */
3039 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3040 {
3041   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3042   tinyInfo.push_back(getMeshDimension());
3043   tinyInfo.push_back(getNumberOfCells());
3044   if(_nodal_connec)
3045     tinyInfo.push_back(getMeshLength());
3046   else
3047     tinyInfo.push_back(-1);
3048 }
3049
3050 /*!
3051  * First step of unserialization process.
3052  */
3053 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3054 {
3055   return tinyInfo[6]<=0;
3056 }
3057
3058 /*!
3059  * Second step of serialization process.
3060  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3061  */
3062 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3063 {
3064   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3065   if(tinyInfo[5]!=-1)
3066     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3067 }
3068
3069 /*!
3070  * Third and final step of serialization process.
3071  */
3072 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3073 {
3074   MEDCouplingPointSet::serialize(a1,a2);
3075   if(getMeshDimension()>-1)
3076     {
3077       a1=DataArrayInt::New();
3078       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3079       int *ptA1=a1->getPointer();
3080       const int *conn=getNodalConnectivity()->getConstPointer();
3081       const int *index=getNodalConnectivityIndex()->getConstPointer();
3082       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3083       std::copy(conn,conn+getMeshLength(),ptA1);
3084     }
3085   else
3086     a1=0;
3087 }
3088
3089 /*!
3090  * Second and final unserialization process.
3091  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3092  */
3093 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3094 {
3095   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3096   setMeshDimension(tinyInfo[5]);
3097   if(tinyInfo[7]!=-1)
3098     {
3099       // Connectivity
3100       const int *recvBuffer=a1->getConstPointer();
3101       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3102       myConnecIndex->alloc(tinyInfo[6]+1,1);
3103       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3104       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3105       myConnec->alloc(tinyInfo[7],1);
3106       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3107       setConnectivity(myConnec, myConnecIndex);
3108     }
3109 }
3110
3111 /*!
3112  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3113  * CellIds are given using range specified by a start an end and step.
3114  */
3115 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3116 {
3117   checkFullyDefined();
3118   int ncell=getNumberOfCells();
3119   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3120   ret->_mesh_dim=_mesh_dim;
3121   ret->setCoords(_coords);
3122   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3123   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3124   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3125   int work=start;
3126   const int *conn=_nodal_connec->getConstPointer();
3127   const int *connIndex=_nodal_connec_index->getConstPointer();
3128   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3129     {
3130       if(work>=0 && work<ncell)
3131         {
3132           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3133         }
3134       else
3135         {
3136           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3137           throw INTERP_KERNEL::Exception(oss.str().c_str());
3138         }
3139     }
3140   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3141   int *newConnPtr=newConn->getPointer();
3142   std::set<INTERP_KERNEL::NormalizedCellType> types;
3143   work=start;
3144   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3145     {
3146       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3147       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3148     }
3149   ret->setConnectivity(newConn,newConnI,false);
3150   ret->_types=types;
3151   ret->copyTinyInfoFrom(this);
3152   return ret.retn();
3153 }
3154
3155 /*!
3156  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3157  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3158  * The return newly allocated mesh will share the same coordinates as \a this.
3159  */
3160 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3161 {
3162   checkConnectivityFullyDefined();
3163   int ncell=getNumberOfCells();
3164   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3165   ret->_mesh_dim=_mesh_dim;
3166   ret->setCoords(_coords);
3167   std::size_t nbOfElemsRet=std::distance(begin,end);
3168   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3169   connIndexRet[0]=0;
3170   const int *conn=_nodal_connec->getConstPointer();
3171   const int *connIndex=_nodal_connec_index->getConstPointer();
3172   int newNbring=0;
3173   for(const int *work=begin;work!=end;work++,newNbring++)
3174     {
3175       if(*work>=0 && *work<ncell)
3176         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3177       else
3178         {
3179           free(connIndexRet);
3180           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3181           throw INTERP_KERNEL::Exception(oss.str().c_str());
3182         }
3183     }
3184   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3185   int *connRetWork=connRet;
3186   std::set<INTERP_KERNEL::NormalizedCellType> types;
3187   for(const int *work=begin;work!=end;work++)
3188     {
3189       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3190       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3191     }
3192   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3193   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3195   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3196   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3197   ret->_types=types;
3198   ret->copyTinyInfoFrom(this);
3199   return ret.retn();
3200 }
3201
3202 /*!
3203  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3204  * mesh.<br>
3205  * For 1D cells, the returned field contains lengths.<br>
3206  * For 2D cells, the returned field contains areas.<br>
3207  * For 3D cells, the returned field contains volumes.
3208  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3209  *         orientation, i.e. the volume is always positive.
3210  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3211  *         and one time . The caller is to delete this field using decrRef() as it is no
3212  *         more needed.
3213  */
3214 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3215 {
3216   std::string name="MeasureOfMesh_";
3217   name+=getName();
3218   int nbelem=getNumberOfCells();
3219   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3220   field->setName(name.c_str());
3221   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3222   array->alloc(nbelem,1);
3223   double *area_vol=array->getPointer();
3224   field->setArray(array) ; array=0;
3225   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3226   field->synchronizeTimeWithMesh();
3227   if(getMeshDimension()!=-1)
3228     {
3229       int ipt;
3230       INTERP_KERNEL::NormalizedCellType type;
3231       int dim_space=getSpaceDimension();
3232       const double *coords=getCoords()->getConstPointer();
3233       const int *connec=getNodalConnectivity()->getConstPointer();
3234       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3235       for(int iel=0;iel<nbelem;iel++)
3236         {
3237           ipt=connec_index[iel];
3238           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3239           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);
3240         }
3241       if(isAbs)
3242         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3243     }
3244   else
3245     {
3246       area_vol[0]=std::numeric_limits<double>::max();
3247     }
3248   return field.retn();
3249 }
3250
3251 /*!
3252  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3253  * mesh.<br>
3254  * For 1D cells, the returned array contains lengths.<br>
3255  * For 2D cells, the returned array contains areas.<br>
3256  * For 3D cells, the returned array contains volumes.
3257  * This method avoids building explicitly a part of \a this mesh to perform the work.
3258  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3259  *         orientation, i.e. the volume is always positive.
3260  *  \param [in] begin - an array of cell ids of interest.
3261  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3262  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3263  *          delete this array using decrRef() as it is no more needed.
3264  * 
3265  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3266  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3267  *  \sa getMeasureField()
3268  */
3269 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3270 {
3271   std::string name="PartMeasureOfMesh_";
3272   name+=getName();
3273   int nbelem=(int)std::distance(begin,end);
3274   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3275   array->setName(name.c_str());
3276   array->alloc(nbelem,1);
3277   double *area_vol=array->getPointer();
3278   if(getMeshDimension()!=-1)
3279     {
3280       int ipt;
3281       INTERP_KERNEL::NormalizedCellType type;
3282       int dim_space=getSpaceDimension();
3283       const double *coords=getCoords()->getConstPointer();
3284       const int *connec=getNodalConnectivity()->getConstPointer();
3285       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3286       for(const int *iel=begin;iel!=end;iel++)
3287         {
3288           ipt=connec_index[*iel];
3289           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3290           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3291         }
3292       if(isAbs)
3293         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3294     }
3295   else
3296     {
3297       area_vol[0]=std::numeric_limits<double>::max();
3298     }
3299   return array.retn();
3300 }
3301
3302 /*!
3303  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3304  * \a this one. The returned field contains the dual cell volume for each corresponding
3305  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3306  *  the dual mesh in P1 sens of \a this.<br>
3307  * For 1D cells, the returned field contains lengths.<br>
3308  * For 2D cells, the returned field contains areas.<br>
3309  * For 3D cells, the returned field contains volumes.
3310  * This method is useful to check "P1*" conservative interpolators.
3311  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3312  *         orientation, i.e. the volume is always positive.
3313  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3314  *          nodes and one time. The caller is to delete this array using decrRef() as
3315  *          it is no more needed.
3316  */
3317 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3318 {
3319   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3320   std::string name="MeasureOnNodeOfMesh_";
3321   name+=getName();
3322   int nbNodes=getNumberOfNodes();
3323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3324   double cst=1./((double)getMeshDimension()+1.);
3325   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3326   array->alloc(nbNodes,1);
3327   double *valsToFill=array->getPointer();
3328   std::fill(valsToFill,valsToFill+nbNodes,0.);
3329   const double *values=tmp->getArray()->getConstPointer();
3330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3332   getReverseNodalConnectivity(da,daInd);
3333   const int *daPtr=da->getConstPointer();
3334   const int *daIPtr=daInd->getConstPointer();
3335   for(int i=0;i<nbNodes;i++)
3336     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3337       valsToFill[i]+=cst*values[*cell];
3338   ret->setMesh(this);
3339   ret->setArray(array);
3340   return ret.retn();
3341 }
3342
3343 /*!
3344  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3345  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3346  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3347  * and are normalized.
3348  * <br> \a this can be either 
3349  * - a  2D mesh in 2D or 3D space or 
3350  * - an 1D mesh in 2D space.
3351  * 
3352  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3353  *          cells and one time. The caller is to delete this field using decrRef() as
3354  *          it is no more needed.
3355  *  \throw If the nodal connectivity of cells is not defined.
3356  *  \throw If the coordinates array is not set.
3357  *  \throw If the mesh dimension is not set.
3358  *  \throw If the mesh and space dimension is not as specified above.
3359  */
3360 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3361 {
3362   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3363     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3364   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3365   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3366   int nbOfCells=getNumberOfCells();
3367   int nbComp=getMeshDimension()+1;
3368   array->alloc(nbOfCells,nbComp);
3369   double *vals=array->getPointer();
3370   const int *connI=_nodal_connec_index->getConstPointer();
3371   const int *conn=_nodal_connec->getConstPointer();
3372   const double *coords=_coords->getConstPointer();
3373   if(getMeshDimension()==2)
3374     {
3375       if(getSpaceDimension()==3)
3376         {
3377           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3378           const double *locPtr=loc->getConstPointer();
3379           for(int i=0;i<nbOfCells;i++,vals+=3)
3380             {
3381               int offset=connI[i];
3382               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3383               double n=INTERP_KERNEL::norm<3>(vals);
3384               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3385             }
3386         }
3387       else
3388         {
3389           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3390           const double *isAbsPtr=isAbs->getArray()->begin();
3391           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3392             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3393         }
3394     }
3395   else//meshdimension==1
3396     {
3397       double tmp[2];
3398       for(int i=0;i<nbOfCells;i++)
3399         {
3400           int offset=connI[i];
3401           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3402           double n=INTERP_KERNEL::norm<2>(tmp);
3403           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3404           *vals++=-tmp[1];
3405           *vals++=tmp[0];
3406         }
3407     }
3408   ret->setArray(array);
3409   ret->setMesh(this);
3410   ret->synchronizeTimeWithSupport();
3411   return ret.retn();
3412 }
3413
3414 /*!
3415  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3416  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3417  * and are normalized.
3418  * <br> \a this can be either 
3419  * - a  2D mesh in 2D or 3D space or 
3420  * - an 1D mesh in 2D space.
3421  * 
3422  * This method avoids building explicitly a part of \a this mesh to perform the work.
3423  *  \param [in] begin - an array of cell ids of interest.
3424  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3425  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3426  *          cells and one time. The caller is to delete this field using decrRef() as
3427  *          it is no more needed.
3428  *  \throw If the nodal connectivity of cells is not defined.
3429  *  \throw If the coordinates array is not set.
3430  *  \throw If the mesh dimension is not set.
3431  *  \throw If the mesh and space dimension is not as specified above.
3432  *  \sa buildOrthogonalField()
3433  *
3434  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3435  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3436  */
3437 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3438 {
3439   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3440     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3441   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3442   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3443   std::size_t nbelems=std::distance(begin,end);
3444   int nbComp=getMeshDimension()+1;
3445   array->alloc((int)nbelems,nbComp);
3446   double *vals=array->getPointer();
3447   const int *connI=_nodal_connec_index->getConstPointer();
3448   const int *conn=_nodal_connec->getConstPointer();
3449   const double *coords=_coords->getConstPointer();
3450   if(getMeshDimension()==2)
3451     {
3452       if(getSpaceDimension()==3)
3453         {
3454           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3455           const double *locPtr=loc->getConstPointer();
3456           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3457             {
3458               int offset=connI[*i];
3459               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3460               double n=INTERP_KERNEL::norm<3>(vals);
3461               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3462             }
3463         }
3464       else
3465         {
3466           for(std::size_t i=0;i<nbelems;i++)
3467             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3468         }
3469     }
3470   else//meshdimension==1
3471     {
3472       double tmp[2];
3473       for(const int *i=begin;i!=end;i++)
3474         {
3475           int offset=connI[*i];
3476           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3477           double n=INTERP_KERNEL::norm<2>(tmp);
3478           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3479           *vals++=-tmp[1];
3480           *vals++=tmp[0];
3481         }
3482     }
3483   ret->setArray(array);
3484   ret->setMesh(this);
3485   ret->synchronizeTimeWithSupport();
3486   return ret.retn();
3487 }
3488
3489 /*!
3490  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3491  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3492  * and are \b not normalized.
3493  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3494  *          cells and one time. The caller is to delete this field using decrRef() as
3495  *          it is no more needed.
3496  *  \throw If the nodal connectivity of cells is not defined.
3497  *  \throw If the coordinates array is not set.
3498  *  \throw If \a this->getMeshDimension() != 1.
3499  *  \throw If \a this mesh includes cells of type other than SEG2.
3500  */
3501 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3502 {
3503    if(getMeshDimension()!=1)
3504     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3505    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3506      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3507    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3508    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3509    int nbOfCells=getNumberOfCells();
3510    int spaceDim=getSpaceDimension();
3511    array->alloc(nbOfCells,spaceDim);
3512    double *pt=array->getPointer();
3513    const double *coo=getCoords()->getConstPointer();
3514    std::vector<int> conn;
3515    conn.reserve(2);
3516    for(int i=0;i<nbOfCells;i++)
3517      {
3518        conn.resize(0);
3519        getNodeIdsOfCell(i,conn);
3520        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3521      }
3522    ret->setArray(array);
3523    ret->setMesh(this);
3524    ret->synchronizeTimeWithSupport();
3525    return ret.retn();   
3526 }
3527
3528 /*!
3529  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3530  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3531  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3532  * from. If a result face is shared by two 3D cells, then the face in included twice in
3533  * the result mesh.
3534  *  \param [in] origin - 3 components of a point defining location of the plane.
3535  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3536  *         must be greater than 1e-6.
3537  *  \param [in] eps - half-thickness of the plane.
3538  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3539  *         producing correspondent 2D cells. The caller is to delete this array
3540  *         using decrRef() as it is no more needed.
3541  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3542  *         not share the node coordinates array with \a this mesh. The caller is to
3543  *         delete this mesh using decrRef() as it is no more needed.  
3544  *  \throw If the coordinates array is not set.
3545  *  \throw If the nodal connectivity of cells is not defined.
3546  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3547  *  \throw If magnitude of \a vec is less than 1e-6.
3548  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3549  *  \throw If \a this includes quadratic cells.
3550  */
3551 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3552 {
3553   checkFullyDefined();
3554   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3555     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3557   if(candidates->empty())
3558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3559   std::vector<int> nodes;
3560   DataArrayInt *cellIds1D=0;
3561   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3562   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3565   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3566   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3567   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3568   revDesc2=0; revDescIndx2=0;
3569   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3570   revDesc1=0; revDescIndx1=0;
3571   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3572   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3573   //
3574   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3575   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3576     cut3DCurve[*it]=-1;
3577   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3578   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3579   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3580                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3581                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3583   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3584   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3585   if(cellIds2->empty())
3586     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3587   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3588   ret->setCoords(mDesc1->getCoords());
3589   ret->setConnectivity(conn,connI,true);
3590   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3591   return ret.retn();
3592 }
3593
3594 /*!
3595  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3596 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
3597 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3598 the result mesh.
3599  *  \param [in] origin - 3 components of a point defining location of the plane.
3600  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3601  *         must be greater than 1e-6.
3602  *  \param [in] eps - half-thickness of the plane.
3603  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3604  *         producing correspondent segments. The caller is to delete this array
3605  *         using decrRef() as it is no more needed.
3606  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3607  *         mesh in 3D space. This mesh does not share the node coordinates array with
3608  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3609  *         no more needed. 
3610  *  \throw If the coordinates array is not set.
3611  *  \throw If the nodal connectivity of cells is not defined.
3612  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3613  *  \throw If magnitude of \a vec is less than 1e-6.
3614  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3615  *  \throw If \a this includes quadratic cells.
3616  */
3617 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3618 {
3619   checkFullyDefined();
3620   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3622   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3623   if(candidates->empty())
3624     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3625   std::vector<int> nodes;
3626   DataArrayInt *cellIds1D=0;
3627   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3628   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3632   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3633   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3634   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3636   //
3637   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3638   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3639     cut3DCurve[*it]=-1;
3640   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3641   int ncellsSub=subMesh->getNumberOfCells();
3642   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3643   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3644                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3645                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3647   conn->alloc(0,1);
3648   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3649   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3650   for(int i=0;i<ncellsSub;i++)
3651     {
3652       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3653         {
3654           if(cut3DSurf[i].first!=-2)
3655             {
3656               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3657               connI->pushBackSilent(conn->getNumberOfTuples());
3658               cellIds2->pushBackSilent(i);
3659             }
3660           else
3661             {
3662               int cellId3DSurf=cut3DSurf[i].second;
3663               int offset=nodalI[cellId3DSurf]+1;
3664               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3665               for(int j=0;j<nbOfEdges;j++)
3666                 {
3667                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3668                   connI->pushBackSilent(conn->getNumberOfTuples());
3669                   cellIds2->pushBackSilent(cellId3DSurf);
3670                 }
3671             }
3672         }
3673     }
3674   if(cellIds2->empty())
3675     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3676   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3677   ret->setCoords(mDesc1->getCoords());
3678   ret->setConnectivity(conn,connI,true);
3679   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3680   return ret.retn();
3681 }
3682
3683 /*!
3684  * Finds cells whose bounding boxes intersect a given plane.
3685  *  \param [in] origin - 3 components of a point defining location of the plane.
3686  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3687  *         must be greater than 1e-6.
3688  *  \param [in] eps - half-thickness of the plane.
3689  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3690  *         cells. The caller is to delete this array using decrRef() as it is no more
3691  *         needed.
3692  *  \throw If the coordinates array is not set.
3693  *  \throw If the nodal connectivity of cells is not defined.
3694  *  \throw If \a this->getSpaceDimension() != 3.
3695  *  \throw If magnitude of \a vec is less than 1e-6.
3696  *  \sa buildSlice3D()
3697  */
3698 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3699 {
3700   checkFullyDefined();
3701   if(getSpaceDimension()!=3)
3702     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3703   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3704   if(normm<1e-6)
3705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3706   double vec2[3];
3707   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3708   double angle=acos(vec[2]/normm);
3709   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3710   double bbox[6];
3711   if(angle>eps)
3712     {
3713       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3714       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3715       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3716       mw->setCoords(coo);
3717       mw->getBoundingBox(bbox);
3718       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3719       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3720     }
3721   else
3722     {
3723       getBoundingBox(bbox);
3724       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3725       cellIds=getCellsInBoundingBox(bbox,eps);
3726     }
3727   return cellIds.retn();
3728 }
3729
3730 /*!
3731  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3732  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3733  * No consideration of coordinate is done by this method.
3734  * 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)
3735  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3736  */
3737 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3738 {
3739   if(getMeshDimension()!=1)
3740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3741   int nbCells=getNumberOfCells();
3742   if(nbCells<1)
3743     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3744   const int *connI=_nodal_connec_index->getConstPointer();
3745   const int *conn=_nodal_connec->getConstPointer();
3746   int ref=conn[connI[0]+2];
3747   for(int i=1;i<nbCells;i++)
3748     {
3749       if(conn[connI[i]+1]!=ref)
3750         return false;
3751       ref=conn[connI[i]+2];
3752     }
3753   return true;
3754 }
3755
3756 /*!
3757  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3758  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3759  * \param pt reference point of the line
3760  * \param v normalized director vector of the line
3761  * \param eps max precision before throwing an exception
3762  * \param res output of size this->getNumberOfCells
3763  */
3764 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3765 {
3766   if(getMeshDimension()!=1)
3767     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3768    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3769      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3770    if(getSpaceDimension()!=3)
3771      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3772    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3773    const double *fPtr=f->getArray()->getConstPointer();
3774    double tmp[3];
3775    for(int i=0;i<getNumberOfCells();i++)
3776      {
3777        const double *tmp1=fPtr+3*i;
3778        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3779        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3780        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3781        double n1=INTERP_KERNEL::norm<3>(tmp);
3782        n1/=INTERP_KERNEL::norm<3>(tmp1);
3783        if(n1>eps)
3784          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3785      }
3786    const double *coo=getCoords()->getConstPointer();
3787    for(int i=0;i<getNumberOfNodes();i++)
3788      {
3789        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3790        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3791        res[i]=std::accumulate(tmp,tmp+3,0.);
3792      }
3793 }
3794
3795 /*!
3796  * 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. 
3797  * \a this is expected to be a mesh so that its space dimension is equal to its
3798  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3799  * 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).
3800  
3801  * 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
3802  * 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).
3803  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3804  *
3805  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3806  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3807  *
3808  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3809  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3810  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3811  * \return the positive value of the distance.
3812  * \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
3813  * dimension - 1.
3814  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3815  */
3816 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3817 {
3818   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3819   if(meshDim!=spaceDim-1)
3820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3821   if(meshDim!=2 && meshDim!=1)
3822     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3823   checkFullyDefined();
3824   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3825     { 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()); }
3826   DataArrayInt *ret1=0;
3827   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3828   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3830   cellId=*ret1Safe->begin();
3831   return *ret0->begin();
3832 }
3833
3834 /*!
3835  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3836  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3837  * 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
3838  * 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).
3839  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3840  * 
3841  * \a this is expected to be a mesh so that its space dimension is equal to its
3842  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3843  * 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).
3844  *
3845  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3846  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3847  *
3848  * \param [in] pts the list of points in which each tuple represents a point
3849  * \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.
3850  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3851  * \throw if number of components of \a pts is not equal to the space dimension.
3852  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3853  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3854  */
3855 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3856 {
3857   if(!pts)
3858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3859   pts->checkAllocated();
3860   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3861   if(meshDim!=spaceDim-1)
3862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3863   if(meshDim!=2 && meshDim!=1)
3864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3865   if(pts->getNumberOfComponents()!=spaceDim)
3866     {
3867       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3868       throw INTERP_KERNEL::Exception(oss.str().c_str());
3869     }
3870   checkFullyDefined();
3871   int nbCells=getNumberOfCells();
3872   if(nbCells==0)
3873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3874   int nbOfPts=pts->getNumberOfTuples();
3875   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3877   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3878   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3879   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3880   const double *bbox(bboxArr->begin());
3881   switch(spaceDim)
3882     {
3883     case 3:
3884       {
3885         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3886         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3887           {
3888             double x=std::numeric_limits<double>::max();
3889             std::vector<int> elems;
3890             myTree.getMinDistanceOfMax(ptsPtr,x);
3891             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3892             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3893           }
3894         break;
3895       }
3896     case 2:
3897       {
3898         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3899         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3900           {
3901             double x=std::numeric_limits<double>::max();
3902             std::vector<int> elems;
3903             myTree.getMinDistanceOfMax(ptsPtr,x);
3904             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3905             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3906           }
3907         break;
3908       }
3909     default:
3910       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3911     }
3912   cellIds=ret1.retn();
3913   return ret0.retn();
3914 }
3915
3916 /*!
3917  * \param [in] pt the start pointer (included) of the coordinates of the point
3918  * \param [in] cellIdsBg the start pointer (included) of cellIds
3919  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3920  * \param [in] nc nodal connectivity
3921  * \param [in] ncI nodal connectivity index
3922  * \param [in,out] ret0 the min distance between \a this and the external input point
3923  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3924  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3925  */
3926 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3927 {
3928   cellId=-1;
3929   ret0=std::numeric_limits<double>::max();
3930   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3931     {
3932       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3933         {
3934         case INTERP_KERNEL::NORM_TRI3:
3935           {
3936             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3937             if(tmp<ret0)
3938               { ret0=tmp; cellId=*zeCell; }
3939             break;
3940           }
3941         case INTERP_KERNEL::NORM_QUAD4:
3942         case INTERP_KERNEL::NORM_POLYGON:
3943           {
3944             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3945             if(tmp<ret0)
3946               { ret0=tmp; cellId=*zeCell; }
3947             break;
3948           }
3949         default:
3950           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3951         }
3952     }
3953 }
3954
3955 /*!
3956  * \param [in] pt the start pointer (included) of the coordinates of the point
3957  * \param [in] cellIdsBg the start pointer (included) of cellIds
3958  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3959  * \param [in] nc nodal connectivity
3960  * \param [in] ncI nodal connectivity index
3961  * \param [in,out] ret0 the min distance between \a this and the external input point
3962  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3963  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3964  */
3965 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3966 {
3967   cellId=-1;
3968   ret0=std::numeric_limits<double>::max();
3969   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3970     {
3971        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3972         {
3973         case INTERP_KERNEL::NORM_SEG2:
3974           {
3975             std::size_t uselessEntry=0;
3976             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3977             tmp=sqrt(tmp);
3978             if(tmp<ret0)
3979               { ret0=tmp; cellId=*zeCell; }
3980             break;
3981           }
3982         default:
3983           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3984         }
3985     }
3986 }
3987
3988 /*!
3989  * Finds cells in contact with a ball (i.e. a point with precision). 
3990  * \warning This method is suitable if the caller intends to evaluate only one
3991  *          point, for more points getCellsContainingPoints() is recommended as it is
3992  *          faster. 
3993  *  \param [in] pos - array of coordinates of the ball central point.
3994  *  \param [in] eps - ball radius.
3995  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
3996  *         if there are no such cells.
3997  *  \throw If the coordinates array is not set.
3998  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3999  */
4000 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4001 {
4002   std::vector<int> elts;
4003   getCellsContainingPoint(pos,eps,elts);
4004   if(elts.empty())
4005     return -1;
4006   return elts.front();
4007 }
4008
4009 /*!
4010  * Finds cells in contact with a ball (i.e. a point with precision).
4011  * \warning This method is suitable if the caller intends to evaluate only one
4012  *          point, for more points getCellsContainingPoints() is recommended as it is
4013  *          faster. 
4014  *  \param [in] pos - array of coordinates of the ball central point.
4015  *  \param [in] eps - ball radius.
4016  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4017  *         before inserting ids.
4018  *  \throw If the coordinates array is not set.
4019  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4020  *
4021  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4022  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4023  */
4024 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4025 {
4026   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4027   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4028   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4029 }
4030
4031 /// @cond INTERNAL
4032
4033 namespace ParaMEDMEM
4034 {
4035   template<const int SPACEDIMM>
4036   class DummyClsMCUG
4037   {
4038   public:
4039     static const int MY_SPACEDIM=SPACEDIMM;
4040     static const int MY_MESHDIM=8;
4041     typedef int MyConnType;
4042     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4043     // begin
4044     // useless, but for windows compilation ...
4045     const double* getCoordinatesPtr() const { return 0; }
4046     const int* getConnectivityPtr() const { return 0; }
4047     const int* getConnectivityIndexPtr() const { return 0; }
4048     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4049     // end
4050   };
4051
4052   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4053   {
4054     INTERP_KERNEL::Edge *ret=0;
4055     switch(typ)
4056       {
4057       case INTERP_KERNEL::NORM_SEG2:
4058         {
4059           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4060           break;
4061         }
4062       case INTERP_KERNEL::NORM_SEG3:
4063         {
4064           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4065           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4066           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4067           bool colinearity=inters.areColinears();
4068           delete e1; delete e2;
4069           if(colinearity)
4070             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4071           else
4072             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4073           mapp2[bg[2]].second=false;
4074           break;
4075         }
4076       default:
4077         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4078       }
4079     return ret;
4080   }
4081
4082   /*!
4083    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4084    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4085    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4086    */
4087   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4088   {
4089     mapp.clear();
4090     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.
4091     const double *coo=mDesc->getCoords()->getConstPointer();
4092     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4093     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4094     std::set<int> s;
4095     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4096       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4097     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4098       {
4099         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4100         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4101       }
4102     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4103     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4104       {
4105         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4106         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4107       }
4108     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4109       {
4110         if((*it2).second.second)
4111           mapp[(*it2).second.first]=(*it2).first;
4112         ((*it2).second.first)->decrRef();
4113       }
4114     return ret;
4115   }
4116
4117   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4118   {
4119     if(nodeId>=offset2)
4120       {
4121         int locId=nodeId-offset2;
4122         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4123       }
4124     if(nodeId>=offset1)
4125       {
4126         int locId=nodeId-offset1;
4127         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4128       }
4129     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4130   }
4131
4132   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4133                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4134                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4135   {
4136     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4137       {
4138         int eltId1=abs(*desc1)-1;
4139         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4140           {
4141             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4142             if(it==mappRev.end())
4143               {
4144                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4145                 mapp[node]=*it1;
4146                 mappRev[*it1]=node;
4147               }
4148           }
4149       }
4150   }
4151 }
4152
4153 /// @endcond
4154
4155 template<int SPACEDIM>
4156 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4157                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4158 {
4159   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4160   int *eltsIndexPtr(eltsIndex->getPointer());
4161   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4162   const double *bbox(bboxArr->begin());
4163   int nbOfCells=getNumberOfCells();
4164   const int *conn=_nodal_connec->getConstPointer();
4165   const int *connI=_nodal_connec_index->getConstPointer();
4166   double bb[2*SPACEDIM];
4167   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4168   for(int i=0;i<nbOfPoints;i++)
4169     {
4170       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4171       for(int j=0;j<SPACEDIM;j++)
4172         {
4173           bb[2*j]=pos[SPACEDIM*i+j];
4174           bb[2*j+1]=pos[SPACEDIM*i+j];
4175         }
4176       std::vector<int> candidates;
4177       myTree.getIntersectingElems(bb,candidates);
4178       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4179         {
4180           int sz=connI[(*iter)+1]-connI[*iter]-1;
4181           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4182                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4183                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4184             {
4185               eltsIndexPtr[i+1]++;
4186               elts->pushBackSilent(*iter);
4187             }
4188         }
4189     }
4190 }
4191 /*!
4192  * Finds cells in contact with several balls (i.e. points with precision).
4193  * This method is an extension of getCellContainingPoint() and
4194  * getCellsContainingPoint() for the case of multiple points.
4195  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4196  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4197  *         this->getSpaceDimension() * \a nbOfPoints 
4198  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4199  *  \param [in] eps - radius of balls (i.e. the precision).
4200  *  \param [out] elts - vector returning ids of found cells.
4201  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4202  *         dividing cell ids in \a elts into groups each referring to one
4203  *         point. Its every element (except the last one) is an index pointing to the
4204  *         first id of a group of cells. For example cells in contact with the *i*-th
4205  *         point are described by following range of indices:
4206  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4207  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4208  *         Number of cells in contact with the *i*-th point is
4209  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4210  *  \throw If the coordinates array is not set.
4211  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4212  *
4213  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4214  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4215  */
4216 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4217                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4218 {
4219   int spaceDim=getSpaceDimension();
4220   int mDim=getMeshDimension();
4221   if(spaceDim==3)
4222     {
4223       if(mDim==3)
4224         {
4225           const double *coords=_coords->getConstPointer();
4226           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4227         }
4228       /*else if(mDim==2)
4229         {
4230           
4231         }*/
4232       else
4233         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4234     }
4235   else if(spaceDim==2)
4236     {
4237       if(mDim==2)
4238         {
4239           const double *coords=_coords->getConstPointer();
4240           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4241         }
4242       else
4243         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4244     }
4245   else if(spaceDim==1)
4246     {
4247       if(mDim==1)
4248         {
4249           const double *coords=_coords->getConstPointer();
4250           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4251         }
4252       else
4253         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4254     }
4255   else
4256     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4257 }
4258
4259 /*!
4260  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4261  * least two its edges intersect each other anywhere except their extremities. An
4262  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4263  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4264  *         cleared before filling in.
4265  *  \param [in] eps - precision.
4266  *  \throw If \a this->getMeshDimension() != 2.
4267  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4268  */
4269 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4270 {
4271   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4272   if(getMeshDimension()!=2)
4273     throw INTERP_KERNEL::Exception(msg);
4274   int spaceDim=getSpaceDimension();
4275   if(spaceDim!=2 && spaceDim!=3)
4276     throw INTERP_KERNEL::Exception(msg);
4277   const int *conn=_nodal_connec->getConstPointer();
4278   const int *connI=_nodal_connec_index->getConstPointer();
4279   int nbOfCells=getNumberOfCells();
4280   std::vector<double> cell2DinS2;
4281   for(int i=0;i<nbOfCells;i++)
4282     {
4283       int offset=connI[i];
4284       int nbOfNodesForCell=connI[i+1]-offset-1;
4285       if(nbOfNodesForCell<=3)
4286         continue;
4287       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4288       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4289       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4290         cells.push_back(i);
4291       cell2DinS2.clear();
4292     }
4293 }
4294
4295 /*!
4296  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4297  *
4298  * 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.
4299  * 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.
4300  * 
4301  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4302  * This convex envelop is computed using Jarvis march algorithm.
4303  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4304  * 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)
4305  * 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.
4306  *
4307  * \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.
4308  */
4309 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4310 {
4311   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4313   checkFullyDefined();
4314   const double *coords=getCoords()->getConstPointer();
4315   int nbOfCells=getNumberOfCells();
4316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4317   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4319   int *workIndexOut=nodalConnecIndexOut->getPointer();
4320   *workIndexOut=0;
4321   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4322   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4323   std::set<INTERP_KERNEL::NormalizedCellType> types;
4324   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4325   isChanged->alloc(0,1);
4326   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4327     {
4328       int pos=nodalConnecOut->getNumberOfTuples();
4329       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4330         isChanged->pushBackSilent(i);
4331       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4332       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4333     }
4334   if(isChanged->empty())
4335     return 0;
4336   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4337   _types=types;
4338   return isChanged.retn();
4339 }
4340
4341 /*!
4342  * This method is \b NOT const because it can modify \a this.
4343  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4344  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4345  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4346  * \b 1 for translation and rotation around point of 'mesh1D'.
4347  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4348  */
4349 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4350 {
4351   checkFullyDefined();
4352   mesh1D->checkFullyDefined();
4353   if(!mesh1D->isContiguous1D())
4354     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4355   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4356     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4357   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4358     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4359   if(mesh1D->getMeshDimension()!=1)
4360     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4361   bool isQuad=false;
4362   if(isPresenceOfQuadratic())
4363     {
4364       if(mesh1D->isFullyQuadratic())
4365         isQuad=true;
4366       else
4367         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4368     }
4369   zipCoords();
4370   int oldNbOfNodes=getNumberOfNodes();
4371   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4372   switch(policy)
4373     {
4374     case 0:
4375       {
4376         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4377         break;
4378       }
4379     case 1:
4380       {
4381         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4382         break;
4383       }
4384     default:
4385       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4386     }
4387   setCoords(newCoords);
4388   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4389   updateTime();
4390   return ret.retn();
4391 }
4392
4393 /*!
4394  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4395  * If it is not the case an exception will be thrown.
4396  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4397  * intersection of plane defined by ('origin','vec').
4398  * This method has one in/out parameter : 'cut3DCurve'.
4399  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4400  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4401  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4402  * This method will throw an exception if \a this contains a non linear segment.
4403  */
4404 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4405 {
4406   checkFullyDefined();
4407   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4409   int ncells=getNumberOfCells();
4410   int nnodes=getNumberOfNodes();
4411   double vec2[3],vec3[3],vec4[3];
4412   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4413   if(normm<1e-6)
4414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4415   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4416   const int *conn=_nodal_connec->getConstPointer();
4417   const int *connI=_nodal_connec_index->getConstPointer();
4418   const double *coo=_coords->getConstPointer();
4419   std::vector<double> addCoo;
4420   for(int i=0;i<ncells;i++)
4421     {
4422       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4423         {
4424           if(cut3DCurve[i]==-2)
4425             {
4426               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4427               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];
4428               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4429               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4430               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4431                 {
4432                   const double *st2=coo+3*st;
4433                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4434                   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]));
4435                   if(pos>eps && pos<1-eps)
4436                     {
4437                       int nNode=((int)addCoo.size())/3;
4438                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4439                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4440                       cut3DCurve[i]=nnodes+nNode;
4441                     }
4442                 }
4443             }
4444         }
4445       else
4446         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4447     }
4448   if(!addCoo.empty())
4449     {
4450       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4451       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4452       coo2->alloc(newNbOfNodes,3);
4453       double *tmp=coo2->getPointer();
4454       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4455       std::copy(addCoo.begin(),addCoo.end(),tmp);
4456       DataArrayDouble::SetArrayIn(coo2,_coords);
4457     }
4458 }
4459
4460 /*!
4461  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4462  * \param mesh1D is the input 1D mesh used for translation computation.
4463  * \return newCoords new coords filled by this method. 
4464  */
4465 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4466 {
4467   int oldNbOfNodes=getNumberOfNodes();
4468   int nbOf1DCells=mesh1D->getNumberOfCells();
4469   int spaceDim=getSpaceDimension();
4470   DataArrayDouble *ret=DataArrayDouble::New();
4471   std::vector<bool> isQuads;
4472   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4473   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4474   double *retPtr=ret->getPointer();
4475   const double *coords=getCoords()->getConstPointer();
4476   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4477   std::vector<int> v;
4478   std::vector<double> c;
4479   double vec[3];
4480   v.reserve(3);
4481   c.reserve(6);
4482   for(int i=0;i<nbOf1DCells;i++)
4483     {
4484       v.resize(0);
4485       mesh1D->getNodeIdsOfCell(i,v);
4486       c.resize(0);
4487       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4488       mesh1D->getCoordinatesOfNode(v[0],c);
4489       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4490       for(int j=0;j<oldNbOfNodes;j++)
4491         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4492       if(isQuad)
4493         {
4494           c.resize(0);
4495           mesh1D->getCoordinatesOfNode(v[1],c);
4496           mesh1D->getCoordinatesOfNode(v[0],c);
4497           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4498           for(int j=0;j<oldNbOfNodes;j++)
4499             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4500         }
4501     }
4502   ret->copyStringInfoFrom(*getCoords());
4503   return ret;
4504 }
4505
4506 /*!
4507  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4508  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4509  * \return newCoords new coords filled by this method. 
4510  */
4511 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4512 {
4513   if(mesh1D->getSpaceDimension()==2)
4514     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4515   if(mesh1D->getSpaceDimension()==3)
4516     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4517   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
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::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4526 {
4527   if(isQuad)
4528     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4529   int oldNbOfNodes=getNumberOfNodes();
4530   int nbOf1DCells=mesh1D->getNumberOfCells();
4531   if(nbOf1DCells<2)
4532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4533   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4534   int nbOfLevsInVec=nbOf1DCells+1;
4535   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4536   double *retPtr=ret->getPointer();
4537   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4538   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4539   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4540   tmp->setCoords(tmp2);
4541   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4542   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4543   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4544   for(int i=1;i<nbOfLevsInVec;i++)
4545     {
4546       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4547       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4548       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4549       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4550       tmp->translate(vec);
4551       double tmp3[2],radius,alpha,alpha0;
4552       const double *p0=i+1<nbOfLevsInVec?begin:third;
4553       const double *p1=i+1<nbOfLevsInVec?end:begin;
4554       const double *p2=i+1<nbOfLevsInVec?third:end;
4555       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4556       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]);
4557       double angle=acos(cosangle/(radius*radius));
4558       tmp->rotate(end,0,angle);
4559       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4560     }
4561   return ret.retn();
4562 }
4563
4564 /*!
4565  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4566  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4567  * \return newCoords new coords filled by this method. 
4568  */
4569 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4570 {
4571   if(isQuad)
4572     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4573   int oldNbOfNodes=getNumberOfNodes();
4574   int nbOf1DCells=mesh1D->getNumberOfCells();
4575   if(nbOf1DCells<2)
4576     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4577   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4578   int nbOfLevsInVec=nbOf1DCells+1;
4579   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4580   double *retPtr=ret->getPointer();
4581   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4582   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4583   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4584   tmp->setCoords(tmp2);
4585   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4586   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4587   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4588   for(int i=1;i<nbOfLevsInVec;i++)
4589     {
4590       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4591       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4592       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4593       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4594       tmp->translate(vec);
4595       double tmp3[2],radius,alpha,alpha0;
4596       const double *p0=i+1<nbOfLevsInVec?begin:third;
4597       const double *p1=i+1<nbOfLevsInVec?end:begin;
4598       const double *p2=i+1<nbOfLevsInVec?third:end;
4599       double vecPlane[3]={
4600         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4601         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4602         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4603       };
4604       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4605       if(norm>1.e-7)
4606         {
4607           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4608           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4609           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4610           double s2=norm2;
4611           double c2=cos(asin(s2));
4612           double m[3][3]={
4613             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4614             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4615             {-vec2[1]*s2, vec2[0]*s2, c2}
4616           };
4617           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]};
4618           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]};
4619           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]};
4620           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4621           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]);
4622           double angle=acos(cosangle/(radius*radius));
4623           tmp->rotate(end,vecPlane,angle);
4624           
4625         }
4626       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4627     }
4628   return ret.retn();
4629 }
4630
4631 /*!
4632  * This method is private because not easy to use for end user. This method is const contrary to
4633  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4634  * the coords sorted slice by slice.
4635  * \param isQuad specifies presence of quadratic cells.
4636  */
4637 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4638 {
4639   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4640   int nbOf2DCells=getNumberOfCells();
4641   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4642   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4643   const int *conn=_nodal_connec->getConstPointer();
4644   const int *connI=_nodal_connec_index->getConstPointer();
4645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4647   newConnI->alloc(nbOf3DCells+1,1);
4648   int *newConnIPtr=newConnI->getPointer();
4649   *newConnIPtr++=0;
4650   std::vector<int> newc;
4651   for(int j=0;j<nbOf2DCells;j++)
4652     {
4653       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4654       *newConnIPtr++=(int)newc.size();
4655     }
4656   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4657   int *newConnPtr=newConn->getPointer();
4658   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4659   newConnIPtr=newConnI->getPointer();
4660   for(int iz=0;iz<nbOf1DCells;iz++)
4661     {
4662       if(iz!=0)
4663         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4664       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4665         {
4666           int icell=(int)(iter-newc.begin());
4667           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4668             {
4669               if(*iter!=-1)
4670                 *newConnPtr=(*iter)+iz*deltaPerLev;
4671               else
4672                 *newConnPtr=-1;
4673             }
4674           else
4675             *newConnPtr=(*iter);
4676         }
4677     }
4678   ret->setConnectivity(newConn,newConnI,true);
4679   ret->setCoords(getCoords());
4680   return ret;
4681 }
4682
4683 /*!
4684  * Checks if \a this mesh is constituted by only quadratic cells.
4685  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4686  *  \throw If the coordinates array is not set.
4687  *  \throw If the nodal connectivity of cells is not defined.
4688  */
4689 bool MEDCouplingUMesh::isFullyQuadratic() const
4690 {
4691   checkFullyDefined();
4692   bool ret=true;
4693   int nbOfCells=getNumberOfCells();
4694   for(int i=0;i<nbOfCells && ret;i++)
4695     {
4696       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4697       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4698       ret=cm.isQuadratic();
4699     }
4700   return ret;
4701 }
4702
4703 /*!
4704  * Checks if \a this mesh includes any quadratic cell.
4705  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4706  *  \throw If the coordinates array is not set.
4707  *  \throw If the nodal connectivity of cells is not defined.
4708  */
4709 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4710 {
4711   checkFullyDefined();
4712   bool ret=false;
4713   int nbOfCells=getNumberOfCells();
4714   for(int i=0;i<nbOfCells && !ret;i++)
4715     {
4716       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4717       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4718       ret=cm.isQuadratic();
4719     }
4720   return ret;
4721 }
4722
4723 /*!
4724  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4725  * this mesh, it remains unchanged.
4726  *  \throw If the coordinates array is not set.
4727  *  \throw If the nodal connectivity of cells is not defined.
4728  */
4729 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4730 {
4731   checkFullyDefined();
4732   int nbOfCells=getNumberOfCells();
4733   int delta=0;
4734   const int *iciptr=_nodal_connec_index->getConstPointer();
4735   for(int i=0;i<nbOfCells;i++)
4736     {
4737       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4738       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4739       if(cm.isQuadratic())
4740         {
4741           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4742           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4743           if(!cml.isDynamic())
4744             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4745           else
4746             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4747         }
4748     }
4749   if(delta==0)
4750     return ;
4751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4753   const int *icptr=_nodal_connec->getConstPointer();
4754   newConn->alloc(getMeshLength()-delta,1);
4755   newConnI->alloc(nbOfCells+1,1);
4756   int *ocptr=newConn->getPointer();
4757   int *ociptr=newConnI->getPointer();
4758   *ociptr=0;
4759   _types.clear();
4760   for(int i=0;i<nbOfCells;i++,ociptr++)
4761     {
4762       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4763       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4764       if(!cm.isQuadratic())
4765         {
4766           _types.insert(type);
4767           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4768           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4769         }
4770       else
4771         {
4772           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4773           _types.insert(typel);
4774           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4775           int newNbOfNodes=cml.getNumberOfNodes();
4776           if(cml.isDynamic())
4777             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4778           *ocptr++=(int)typel;
4779           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4780           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4781         }
4782     }
4783   setConnectivity(newConn,newConnI,false);
4784 }
4785
4786 /*!
4787  * This method converts all linear cell in \a this to quadratic one.
4788  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4789  * 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)
4790  * 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.
4791  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4792  * end of the existing coordinates.
4793  * 
4794  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4795  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4796  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4797  * 
4798  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4799  *
4800  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4801  */
4802 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4803 {
4804   DataArrayInt *conn=0,*connI=0;
4805   DataArrayDouble *coords=0;
4806   std::set<INTERP_KERNEL::NormalizedCellType> types;
4807   checkFullyDefined();
4808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4809   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4810   int meshDim=getMeshDimension();
4811   switch(conversionType)
4812     {
4813     case 0:
4814       switch(meshDim)
4815         {
4816         case 1:
4817           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4818           connSafe=conn; connISafe=connI; coordsSafe=coords;
4819           break;
4820         case 2:
4821           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4822           connSafe=conn; connISafe=connI; coordsSafe=coords;
4823           break;
4824         case 3:
4825           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4826           connSafe=conn; connISafe=connI; coordsSafe=coords;
4827           break;
4828         default:
4829           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4830         }
4831       break;
4832     case 1:
4833       {
4834         switch(meshDim)
4835         {
4836         case 1:
4837           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4838           connSafe=conn; connISafe=connI; coordsSafe=coords;
4839           break;
4840         case 2:
4841           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4842           connSafe=conn; connISafe=connI; coordsSafe=coords;
4843           break;
4844         case 3:
4845           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4846           connSafe=conn; connISafe=connI; coordsSafe=coords;
4847           break;
4848         default:
4849           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4850         }
4851         break;
4852       }
4853     default:
4854       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4855     }
4856   setConnectivity(connSafe,connISafe,false);
4857   _types=types;
4858   setCoords(coordsSafe);
4859   return ret.retn();
4860 }
4861
4862 /*!
4863  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4864  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4865  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4866  */
4867 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4868 {
4869   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4872   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4873   int nbOfCells=getNumberOfCells();
4874   int nbOfNodes=getNumberOfNodes();
4875   const int *cPtr=_nodal_connec->getConstPointer();
4876   const int *icPtr=_nodal_connec_index->getConstPointer();
4877   int lastVal=0,offset=nbOfNodes;
4878   for(int i=0;i<nbOfCells;i++,icPtr++)
4879     {
4880       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4881       if(type==INTERP_KERNEL::NORM_SEG2)
4882         {
4883           types.insert(INTERP_KERNEL::NORM_SEG3);
4884           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4885           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4886           newConn->pushBackSilent(offset++);
4887           lastVal+=4;
4888           newConnI->pushBackSilent(lastVal);
4889           ret->pushBackSilent(i);
4890         }
4891       else
4892         {
4893           types.insert(type);
4894           lastVal+=(icPtr[1]-icPtr[0]);
4895           newConnI->pushBackSilent(lastVal);
4896           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4897         }
4898     }
4899   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4900   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4901   return ret.retn();
4902 }
4903
4904 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4905 {
4906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4909   //
4910   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4911   DataArrayInt *conn1D=0,*conn1DI=0;
4912   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4913   DataArrayDouble *coordsTmp=0;
4914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4915   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4916   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4917   const int *c1DPtr=conn1D->begin();
4918   const int *c1DIPtr=conn1DI->begin();
4919   int nbOfCells=getNumberOfCells();
4920   const int *cPtr=_nodal_connec->getConstPointer();
4921   const int *icPtr=_nodal_connec_index->getConstPointer();
4922   int lastVal=0;
4923   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4924     {
4925       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4926       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4927       if(!cm.isQuadratic())
4928         {
4929           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4930           types.insert(typ2); newConn->pushBackSilent(typ2);
4931           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4932           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4933             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4934           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4935           newConnI->pushBackSilent(lastVal);
4936           ret->pushBackSilent(i);
4937         }
4938       else
4939         {
4940           types.insert(typ);
4941           lastVal+=(icPtr[1]-icPtr[0]);
4942           newConnI->pushBackSilent(lastVal);
4943           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4944         }
4945     }
4946   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4947   return ret.retn();
4948 }
4949
4950 /*!
4951  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4952  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4953  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4954  */
4955 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4956 {
4957   
4958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4959   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4960   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4961 }
4962
4963 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4964 {
4965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4966   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4967   //
4968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4971   //
4972   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4973   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4974   DataArrayInt *conn1D=0,*conn1DI=0;
4975   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4976   DataArrayDouble *coordsTmp=0;
4977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4978   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4980   const int *c1DPtr=conn1D->begin();
4981   const int *c1DIPtr=conn1DI->begin();
4982   int nbOfCells=getNumberOfCells();
4983   const int *cPtr=_nodal_connec->getConstPointer();
4984   const int *icPtr=_nodal_connec_index->getConstPointer();
4985   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4986   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4987     {
4988       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4989       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4990       if(!cm.isQuadratic())
4991         {
4992           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4993           types.insert(typ2); newConn->pushBackSilent(typ2);
4994           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4995           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4996             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4997           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4998           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4999           newConnI->pushBackSilent(lastVal);
5000           ret->pushBackSilent(i);
5001         }
5002       else
5003         {
5004           types.insert(typ);
5005           lastVal+=(icPtr[1]-icPtr[0]);
5006           newConnI->pushBackSilent(lastVal);
5007           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5008         }
5009     }
5010   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5011   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5012   return ret.retn();
5013 }
5014
5015 /*!
5016  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5017  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5018  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5019  */
5020 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5021 {
5022   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5023   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5024   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5025 }
5026
5027 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5028 {
5029   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5030   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5032   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5033   //
5034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5037   //
5038   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5039   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5040   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5041   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5042   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5046   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5049   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5050   int nbOfCells=getNumberOfCells();
5051   const int *cPtr=_nodal_connec->getConstPointer();
5052   const int *icPtr=_nodal_connec_index->getConstPointer();
5053   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5054   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5055     {
5056       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5057       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5058       if(!cm.isQuadratic())
5059         {
5060           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5061           if(typ2==INTERP_KERNEL::NORM_ERROR)
5062             {
5063               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5064               throw INTERP_KERNEL::Exception(oss.str().c_str());
5065             }
5066           types.insert(typ2); newConn->pushBackSilent(typ2);
5067           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5068           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5069             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5070           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5071             {
5072               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5073               int tmpPos=newConn->getNumberOfTuples();
5074               newConn->pushBackSilent(nodeId2);
5075               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5076             }
5077           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5078           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5079           newConnI->pushBackSilent(lastVal);
5080           ret->pushBackSilent(i);
5081         }
5082       else
5083         {
5084           types.insert(typ);
5085           lastVal+=(icPtr[1]-icPtr[0]);
5086           newConnI->pushBackSilent(lastVal);
5087           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5088         }
5089     }
5090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5091   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5092   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5093   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5094   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5095   int *c=newConn->getPointer();
5096   const int *cI(newConnI->begin());
5097   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5098     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5099   offset=coordsTmp2Safe->getNumberOfTuples();
5100   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5101     c[cI[(*elt)+1]-1]+=offset;
5102   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5103   return ret.retn();
5104 }
5105
5106 /*!
5107  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5108  * so that the number of cells remains the same. Quadratic faces are converted to
5109  * polygons. This method works only for 2D meshes in
5110  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5111  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5112  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5113  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5114  *         a polylinized edge constituting the input polygon.
5115  *  \throw If the coordinates array is not set.
5116  *  \throw If the nodal connectivity of cells is not defined.
5117  *  \throw If \a this->getMeshDimension() != 2.
5118  *  \throw If \a this->getSpaceDimension() != 2.
5119  */
5120 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5121 {
5122   checkFullyDefined();
5123   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5124     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5125   double epsa=fabs(eps);
5126   if(epsa<std::numeric_limits<double>::min())
5127     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 !");
5128   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5129   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5131   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5132   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5133   revDesc1=0; revDescIndx1=0;
5134   mDesc->tessellate2DCurve(eps);
5135   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5136   setCoords(mDesc->getCoords());
5137 }
5138
5139 /*!
5140  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5141  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5142  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5143  *         a sub-divided edge.
5144  *  \throw If the coordinates array is not set.
5145  *  \throw If the nodal connectivity of cells is not defined.
5146  *  \throw If \a this->getMeshDimension() != 1.
5147  *  \throw If \a this->getSpaceDimension() != 2.
5148  */
5149 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5150 {
5151   checkFullyDefined();
5152   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5154   double epsa=fabs(eps);
5155   if(epsa<std::numeric_limits<double>::min())
5156     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 !");
5157   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5158   int nbCells=getNumberOfCells();
5159   int nbNodes=getNumberOfNodes();
5160   const int *conn=_nodal_connec->getConstPointer();
5161   const int *connI=_nodal_connec_index->getConstPointer();
5162   const double *coords=_coords->getConstPointer();
5163   std::vector<double> addCoo;
5164   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5166   newConnI->alloc(nbCells+1,1);
5167   int *newConnIPtr=newConnI->getPointer();
5168   *newConnIPtr=0;
5169   int tmp1[3];
5170   INTERP_KERNEL::Node *tmp2[3];
5171   std::set<INTERP_KERNEL::NormalizedCellType> types;
5172   for(int i=0;i<nbCells;i++,newConnIPtr++)
5173     {
5174       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5175       if(cm.isQuadratic())
5176         {//assert(connI[i+1]-connI[i]-1==3)
5177           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5178           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5179           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5180           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5181           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5182           if(eac)
5183             {
5184               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5185               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5186               delete eac;
5187               newConnIPtr[1]=(int)newConn.size();
5188             }
5189           else
5190             {
5191               types.insert(INTERP_KERNEL::NORM_SEG2);
5192               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5193               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5194               newConnIPtr[1]=newConnIPtr[0]+3;
5195             }
5196         }
5197       else
5198         {
5199           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5200           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5201           newConnIPtr[1]=newConnIPtr[0]+3;
5202         }
5203     }
5204   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5205     return ;
5206   _types=types;
5207   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5209   newConnArr->alloc((int)newConn.size(),1);
5210   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5211   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5213   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5214   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5215   std::copy(addCoo.begin(),addCoo.end(),work);
5216   DataArrayDouble::SetArrayIn(newCoords,_coords);
5217   updateTime();
5218 }
5219
5220 /*!
5221  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5222  * In addition, returns an array mapping new cells to old ones. <br>
5223  * This method typically increases the number of cells in \a this mesh
5224  * but the number of nodes remains \b unchanged.
5225  * That's why the 3D splitting policies
5226  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5227  *  \param [in] policy - specifies a pattern used for splitting.
5228  * The semantic of \a policy is:
5229  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5230  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5231  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5232  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5233  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5234  *          an id of old cell producing it. The caller is to delete this array using
5235  *         decrRef() as it is no more needed. 
5236  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5237  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5238  *          and \a this->getMeshDimension() != 3. 
5239  *  \throw If \a policy is not one of the four discussed above.
5240  *  \throw If the nodal connectivity of cells is not defined.
5241  * \sa MEDCouplingUMesh::tetrahedrize
5242  */
5243 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5244 {
5245   switch(policy)
5246     {
5247     case 0:
5248       return simplexizePol0();
5249     case 1:
5250       return simplexizePol1();
5251     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5252       return simplexizePlanarFace5();
5253     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5254       return simplexizePlanarFace6();
5255     default:
5256       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)");
5257     }
5258 }
5259
5260 /*!
5261  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5262  * - 1D: INTERP_KERNEL::NORM_SEG2
5263  * - 2D: INTERP_KERNEL::NORM_TRI3
5264  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5265  *
5266  * This method is useful for users that need to use P1 field services as
5267  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5268  * All these methods need mesh support containing only simplex cells.
5269  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5270  *  \throw If the coordinates array is not set.
5271  *  \throw If the nodal connectivity of cells is not defined.
5272  *  \throw If \a this->getMeshDimension() < 1.
5273  */
5274 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5275 {
5276   checkFullyDefined();
5277   int mdim=getMeshDimension();
5278   if(mdim<1 || mdim>3)
5279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5280   int nbCells=getNumberOfCells();
5281   const int *conn=_nodal_connec->getConstPointer();
5282   const int *connI=_nodal_connec_index->getConstPointer();
5283   for(int i=0;i<nbCells;i++)
5284     {
5285       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5286       if(!cm.isSimplex())
5287         return false;
5288     }
5289   return true;
5290 }
5291
5292 /*!
5293  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5294  */
5295 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5296 {
5297   checkConnectivityFullyDefined();
5298   if(getMeshDimension()!=2)
5299     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5300   int nbOfCells=getNumberOfCells();
5301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5302   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5303   ret->alloc(nbOfCells+nbOfCutCells,1);
5304   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5305   int *retPt=ret->getPointer();
5306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5308   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5309   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5310   int *pt=newConn->getPointer();
5311   int *ptI=newConnI->getPointer();
5312   ptI[0]=0;
5313   const int *oldc=_nodal_connec->getConstPointer();
5314   const int *ci=_nodal_connec_index->getConstPointer();
5315   for(int i=0;i<nbOfCells;i++,ci++)
5316     {
5317       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5318         {
5319           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5320                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5321           pt=std::copy(tmp,tmp+8,pt);
5322           ptI[1]=ptI[0]+4;
5323           ptI[2]=ptI[0]+8;
5324           *retPt++=i;
5325           *retPt++=i;
5326           ptI+=2;
5327         }
5328       else
5329         {
5330           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5331           ptI[1]=ptI[0]+ci[1]-ci[0];
5332           ptI++;
5333           *retPt++=i;
5334         }
5335     }
5336   _nodal_connec->decrRef();
5337   _nodal_connec=newConn.retn();
5338   _nodal_connec_index->decrRef();
5339   _nodal_connec_index=newConnI.retn();
5340   computeTypes();
5341   updateTime();
5342   return ret.retn();
5343 }
5344
5345 /*!
5346  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5347  */
5348 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5349 {
5350   checkConnectivityFullyDefined();
5351   if(getMeshDimension()!=2)
5352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5353   int nbOfCells=getNumberOfCells();
5354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5355   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5356   ret->alloc(nbOfCells+nbOfCutCells,1);
5357   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5358   int *retPt=ret->getPointer();
5359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5361   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5362   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5363   int *pt=newConn->getPointer();
5364   int *ptI=newConnI->getPointer();
5365   ptI[0]=0;
5366   const int *oldc=_nodal_connec->getConstPointer();
5367   const int *ci=_nodal_connec_index->getConstPointer();
5368   for(int i=0;i<nbOfCells;i++,ci++)
5369     {
5370       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5371         {
5372           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5373                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5374           pt=std::copy(tmp,tmp+8,pt);
5375           ptI[1]=ptI[0]+4;
5376           ptI[2]=ptI[0]+8;
5377           *retPt++=i;
5378           *retPt++=i;
5379           ptI+=2;
5380         }
5381       else
5382         {
5383           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5384           ptI[1]=ptI[0]+ci[1]-ci[0];
5385           ptI++;
5386           *retPt++=i;
5387         }
5388     }
5389   _nodal_connec->decrRef();
5390   _nodal_connec=newConn.retn();
5391   _nodal_connec_index->decrRef();
5392   _nodal_connec_index=newConnI.retn();
5393   computeTypes();
5394   updateTime();
5395   return ret.retn();
5396 }
5397
5398 /*!
5399  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5400  */
5401 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5402 {
5403   checkConnectivityFullyDefined();
5404   if(getMeshDimension()!=3)
5405     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5406   int nbOfCells=getNumberOfCells();
5407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5408   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5409   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5410   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5411   int *retPt=ret->getPointer();
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5414   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5415   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5416   int *pt=newConn->getPointer();
5417   int *ptI=newConnI->getPointer();
5418   ptI[0]=0;
5419   const int *oldc=_nodal_connec->getConstPointer();
5420   const int *ci=_nodal_connec_index->getConstPointer();
5421   for(int i=0;i<nbOfCells;i++,ci++)
5422     {
5423       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5424         {
5425           for(int j=0;j<5;j++,pt+=5,ptI++)
5426             {
5427               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5428               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];
5429               *retPt++=i;
5430               ptI[1]=ptI[0]+5;
5431             }
5432         }
5433       else
5434         {
5435           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5436           ptI[1]=ptI[0]+ci[1]-ci[0];
5437           ptI++;
5438           *retPt++=i;
5439         }
5440     }
5441   _nodal_connec->decrRef();
5442   _nodal_connec=newConn.retn();
5443   _nodal_connec_index->decrRef();
5444   _nodal_connec_index=newConnI.retn();
5445   computeTypes();
5446   updateTime();
5447   return ret.retn();
5448 }
5449
5450 /*!
5451  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5452  */
5453 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5454 {
5455   checkConnectivityFullyDefined();
5456   if(getMeshDimension()!=3)
5457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5458   int nbOfCells=getNumberOfCells();
5459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5460   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5461   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5462   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5463   int *retPt=ret->getPointer();
5464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5466   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5467   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5468   int *pt=newConn->getPointer();
5469   int *ptI=newConnI->getPointer();
5470   ptI[0]=0;
5471   const int *oldc=_nodal_connec->getConstPointer();
5472   const int *ci=_nodal_connec_index->getConstPointer();
5473   for(int i=0;i<nbOfCells;i++,ci++)
5474     {
5475       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5476         {
5477           for(int j=0;j<6;j++,pt+=5,ptI++)
5478             {
5479               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5480               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];
5481               *retPt++=i;
5482               ptI[1]=ptI[0]+5;
5483             }
5484         }
5485       else
5486         {
5487           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5488           ptI[1]=ptI[0]+ci[1]-ci[0];
5489           ptI++;
5490           *retPt++=i;
5491         }
5492     }
5493   _nodal_connec->decrRef();
5494   _nodal_connec=newConn.retn();
5495   _nodal_connec_index->decrRef();
5496   _nodal_connec_index=newConnI.retn();
5497   computeTypes();
5498   updateTime();
5499   return ret.retn();
5500 }
5501
5502 /*!
5503  * 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.
5504  * This method completly ignore coordinates.
5505  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5506  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5507  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5508  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5509  */
5510 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5511 {
5512   checkFullyDefined();
5513   if(getMeshDimension()!=2)
5514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5515   int nbOfCells=getNumberOfCells();
5516   int *connI=_nodal_connec_index->getPointer();
5517   int newConnLgth=0;
5518   for(int i=0;i<nbOfCells;i++,connI++)
5519     {
5520       int offset=descIndex[i];
5521       int nbOfEdges=descIndex[i+1]-offset;
5522       //
5523       bool ddirect=desc[offset+nbOfEdges-1]>0;
5524       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5525       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5526       for(int j=0;j<nbOfEdges;j++)
5527         {
5528           bool direct=desc[offset+j]>0;
5529           int edgeId=std::abs(desc[offset+j])-1;
5530           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5531             {
5532               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5533               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5534               int ref2=direct?id1:id2;
5535               if(ref==ref2)
5536                 {
5537                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5538                   newConnLgth+=nbOfSubNodes-1;
5539                   ref=direct?id2:id1;
5540                 }
5541               else
5542                 {
5543                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5544                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5545                 }
5546             }
5547           else
5548             {
5549               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5550             }
5551         }
5552       newConnLgth++;//+1 is for cell type
5553       connI[1]=newConnLgth;
5554     }
5555   //
5556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5557   newConn->alloc(newConnLgth,1);
5558   int *work=newConn->getPointer();
5559   for(int i=0;i<nbOfCells;i++)
5560     {
5561       *work++=INTERP_KERNEL::NORM_POLYGON;
5562       int offset=descIndex[i];
5563       int nbOfEdges=descIndex[i+1]-offset;
5564       for(int j=0;j<nbOfEdges;j++)
5565         {
5566           bool direct=desc[offset+j]>0;
5567           int edgeId=std::abs(desc[offset+j])-1;
5568           if(direct)
5569             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5570           else
5571             {
5572               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5573               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5574               work=std::copy(it,it+nbOfSubNodes-1,work);
5575             }
5576         }
5577     }
5578   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5579   _types.clear();
5580   if(nbOfCells>0)
5581     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5582 }
5583
5584 /*!
5585  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5586  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5587  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5588  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5589  * so it can be useful to call mergeNodes() before calling this method.
5590  *  \throw If \a this->getMeshDimension() <= 1.
5591  *  \throw If the coordinates array is not set.
5592  *  \throw If the nodal connectivity of cells is not defined.
5593  */
5594 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5595 {
5596   checkFullyDefined();
5597   if(getMeshDimension()<=1)
5598     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5599   int nbOfCells=getNumberOfCells();
5600   if(nbOfCells<1)
5601     return ;
5602   int initMeshLgth=getMeshLength();
5603   int *conn=_nodal_connec->getPointer();
5604   int *index=_nodal_connec_index->getPointer();
5605   int posOfCurCell=0;
5606   int newPos=0;
5607   int lgthOfCurCell;
5608   for(int i=0;i<nbOfCells;i++)
5609     {
5610       lgthOfCurCell=index[i+1]-posOfCurCell;
5611       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5612       int newLgth;
5613       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5614                                                                                                      conn+newPos+1,newLgth);
5615       conn[newPos]=newType;
5616       newPos+=newLgth+1;
5617       posOfCurCell=index[i+1];
5618       index[i+1]=newPos;
5619     }
5620   if(newPos!=initMeshLgth)
5621     _nodal_connec->reAlloc(newPos);
5622   computeTypes();
5623 }
5624
5625 /*!
5626  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5627  * A cell is considered to be oriented correctly if an angle between its
5628  * normal vector and a given vector is less than \c PI / \c 2.
5629  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5630  *         cells. 
5631  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5632  *         checked.
5633  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5634  *         is not cleared before filling in.
5635  *  \throw If \a this->getMeshDimension() != 2.
5636  *  \throw If \a this->getSpaceDimension() != 3.
5637  *
5638  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5639  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5640  */
5641 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5642 {
5643   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5644     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5645   int nbOfCells=getNumberOfCells();
5646   const int *conn=_nodal_connec->getConstPointer();
5647   const int *connI=_nodal_connec_index->getConstPointer();
5648   const double *coordsPtr=_coords->getConstPointer();
5649   for(int i=0;i<nbOfCells;i++)
5650     {
5651       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5652       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5653         {
5654           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5655           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5656             cells.push_back(i);
5657         }
5658     }
5659 }
5660
5661 /*!
5662  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5663  * considered to be oriented correctly if an angle between its normal vector and a
5664  * given vector is less than \c PI / \c 2. 
5665  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5666  *         cells. 
5667  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5668  *         checked.
5669  *  \throw If \a this->getMeshDimension() != 2.
5670  *  \throw If \a this->getSpaceDimension() != 3.
5671  *
5672  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5673  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5674  */
5675 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5676 {
5677   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5678     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5679   int nbOfCells=getNumberOfCells();
5680   int *conn=_nodal_connec->getPointer();
5681   const int *connI=_nodal_connec_index->getConstPointer();
5682   const double *coordsPtr=_coords->getConstPointer();
5683   bool isModified=false;
5684   for(int i=0;i<nbOfCells;i++)
5685     {
5686       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5687       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5688         {
5689           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5690           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5691             {
5692               isModified=true;
5693               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5694               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5695               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5696             }
5697         }
5698     }
5699   if(isModified)
5700     _nodal_connec->declareAsNew();
5701   updateTime();
5702 }
5703
5704 /*!
5705  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5706  * oriented facets. The normal vector of the facet should point out of the cell.
5707  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5708  *         is not cleared before filling in.
5709  *  \throw If \a this->getMeshDimension() != 3.
5710  *  \throw If \a this->getSpaceDimension() != 3.
5711  *  \throw If the coordinates array is not set.
5712  *  \throw If the nodal connectivity of cells is not defined.
5713  *
5714  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5715  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5716  */
5717 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5718 {
5719   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5720     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5721   int nbOfCells=getNumberOfCells();
5722   const int *conn=_nodal_connec->getConstPointer();
5723   const int *connI=_nodal_connec_index->getConstPointer();
5724   const double *coordsPtr=_coords->getConstPointer();
5725   for(int i=0;i<nbOfCells;i++)
5726     {
5727       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5728       if(type==INTERP_KERNEL::NORM_POLYHED)
5729         {
5730           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5731             cells.push_back(i);
5732         }
5733     }
5734 }
5735
5736 /*!
5737  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5738  * out of the cell. 
5739  *  \throw If \a this->getMeshDimension() != 3.
5740  *  \throw If \a this->getSpaceDimension() != 3.
5741  *  \throw If the coordinates array is not set.
5742  *  \throw If the nodal connectivity of cells is not defined.
5743  *  \throw If the reparation fails.
5744  *
5745  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5746  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5747  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5748  */
5749 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5750 {
5751   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5752     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5753   int nbOfCells=getNumberOfCells();
5754   int *conn=_nodal_connec->getPointer();
5755   const int *connI=_nodal_connec_index->getConstPointer();
5756   const double *coordsPtr=_coords->getConstPointer();
5757   for(int i=0;i<nbOfCells;i++)
5758     {
5759       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5760       if(type==INTERP_KERNEL::NORM_POLYHED)
5761         {
5762           try
5763             {
5764               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5765                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5766             }
5767           catch(INTERP_KERNEL::Exception& e)
5768             {
5769               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5770               throw INTERP_KERNEL::Exception(oss.str().c_str());
5771             }
5772         }
5773     }
5774   updateTime();
5775 }
5776
5777 /*!
5778  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5779  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5780  * according to which the first facet of the cell should be oriented to have the normal vector
5781  * pointing out of cell.
5782  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5783  *         cells. The caller is to delete this array using decrRef() as it is no more
5784  *         needed. 
5785  *  \throw If \a this->getMeshDimension() != 3.
5786  *  \throw If \a this->getSpaceDimension() != 3.
5787  *  \throw If the coordinates array is not set.
5788  *  \throw If the nodal connectivity of cells is not defined.
5789  *
5790  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5791  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5792  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5793  */
5794 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5795 {
5796   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5797   if(getMeshDimension()!=3)
5798     throw INTERP_KERNEL::Exception(msg);
5799   int spaceDim=getSpaceDimension();
5800   if(spaceDim!=3)
5801     throw INTERP_KERNEL::Exception(msg);
5802   //
5803   int nbOfCells=getNumberOfCells();
5804   int *conn=_nodal_connec->getPointer();
5805   const int *connI=_nodal_connec_index->getConstPointer();
5806   const double *coo=getCoords()->getConstPointer();
5807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5808   for(int i=0;i<nbOfCells;i++)
5809     {
5810       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5811       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5812         {
5813           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5814             {
5815               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5816               cells->pushBackSilent(i);
5817             }
5818         }
5819     }
5820   return cells.retn();
5821 }
5822
5823 /*!
5824  * This method is a faster method to correct orientation of all 3D cells in \a this.
5825  * 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.
5826  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5827  * 
5828  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5829  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5830  */
5831 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5832 {
5833   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5834     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5835   int nbOfCells=getNumberOfCells();
5836   int *conn=_nodal_connec->getPointer();
5837   const int *connI=_nodal_connec_index->getConstPointer();
5838   const double *coordsPtr=_coords->getConstPointer();
5839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5840   for(int i=0;i<nbOfCells;i++)
5841     {
5842       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5843       switch(type)
5844         {
5845         case INTERP_KERNEL::NORM_TETRA4:
5846           {
5847             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5848               {
5849                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5850                 ret->pushBackSilent(i);
5851               }
5852             break;
5853           }
5854         case INTERP_KERNEL::NORM_PYRA5:
5855           {
5856             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5857               {
5858                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5859                 ret->pushBackSilent(i);
5860               }
5861             break;
5862           }
5863         case INTERP_KERNEL::NORM_PENTA6:
5864         case INTERP_KERNEL::NORM_HEXA8:
5865         case INTERP_KERNEL::NORM_HEXGP12:
5866           {
5867             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5868               {
5869                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5870                 ret->pushBackSilent(i);
5871               }
5872             break;
5873           }
5874         case INTERP_KERNEL::NORM_POLYHED:
5875           {
5876             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5877               {
5878                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5879                 ret->pushBackSilent(i);
5880               }
5881             break;
5882           }
5883         default:
5884           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 !");
5885         }
5886     }
5887   updateTime();
5888   return ret.retn();
5889 }
5890
5891 /*!
5892  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5893  * If it is not the case an exception will be thrown.
5894  * This method is fast because the first cell of \a this is used to compute the plane.
5895  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5896  * \param pos output of size at least 3 used to store a point owned of searched plane.
5897  */
5898 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5899 {
5900   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5901     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5902   const int *conn=_nodal_connec->getConstPointer();
5903   const int *connI=_nodal_connec_index->getConstPointer();
5904   const double *coordsPtr=_coords->getConstPointer();
5905   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5906   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5907 }
5908
5909 /*!
5910  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5911  * cells. Currently cells of the following types are treated:
5912  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5913  * For a cell of other type an exception is thrown.
5914  * Space dimension of a 2D mesh can be either 2 or 3.
5915  * The Edge Ratio of a cell \f$t\f$ is: 
5916  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5917  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5918  *  the smallest edge lengths of \f$t\f$.
5919  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5920  *          cells and one time, lying on \a this mesh. The caller is to delete this
5921  *          field using decrRef() as it is no more needed. 
5922  *  \throw If the coordinates array is not set.
5923  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5924  *  \throw If the connectivity data array has more than one component.
5925  *  \throw If the connectivity data array has a named component.
5926  *  \throw If the connectivity index data array has more than one component.
5927  *  \throw If the connectivity index data array has a named component.
5928  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5929  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5930  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5931  */
5932 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5933 {
5934   checkCoherency();
5935   int spaceDim=getSpaceDimension();
5936   int meshDim=getMeshDimension();
5937   if(spaceDim!=2 && spaceDim!=3)
5938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5939   if(meshDim!=2 && meshDim!=3)
5940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5941   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5942   ret->setMesh(this);
5943   int nbOfCells=getNumberOfCells();
5944   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5945   arr->alloc(nbOfCells,1);
5946   double *pt=arr->getPointer();
5947   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5948   const int *conn=_nodal_connec->getConstPointer();
5949   const int *connI=_nodal_connec_index->getConstPointer();
5950   const double *coo=_coords->getConstPointer();
5951   double tmp[12];
5952   for(int i=0;i<nbOfCells;i++,pt++)
5953     {
5954       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5955       switch(t)
5956         {
5957           case INTERP_KERNEL::NORM_TRI3:
5958             {
5959               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5960               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5961               break;
5962             }
5963           case INTERP_KERNEL::NORM_QUAD4:
5964             {
5965               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5966               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5967               break;
5968             }
5969           case INTERP_KERNEL::NORM_TETRA4:
5970             {
5971               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5972               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5973               break;
5974             }
5975         default:
5976           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5977         }
5978       conn+=connI[i+1]-connI[i];
5979     }
5980   ret->setName("EdgeRatio");
5981   ret->synchronizeTimeWithSupport();
5982   return ret.retn();
5983 }
5984
5985 /*!
5986  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5987  * cells. Currently cells of the following types are treated:
5988  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5989  * For a cell of other type an exception is thrown.
5990  * Space dimension of a 2D mesh can be either 2 or 3.
5991  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5992  *          cells and one time, lying on \a this mesh. The caller is to delete this
5993  *          field using decrRef() as it is no more needed. 
5994  *  \throw If the coordinates array is not set.
5995  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5996  *  \throw If the connectivity data array has more than one component.
5997  *  \throw If the connectivity data array has a named component.
5998  *  \throw If the connectivity index data array has more than one component.
5999  *  \throw If the connectivity index data array has a named component.
6000  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6001  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6002  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6003  */
6004 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6005 {
6006   checkCoherency();
6007   int spaceDim=getSpaceDimension();
6008   int meshDim=getMeshDimension();
6009   if(spaceDim!=2 && spaceDim!=3)
6010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6011   if(meshDim!=2 && meshDim!=3)
6012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6013   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6014   ret->setMesh(this);
6015   int nbOfCells=getNumberOfCells();
6016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6017   arr->alloc(nbOfCells,1);
6018   double *pt=arr->getPointer();
6019   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6020   const int *conn=_nodal_connec->getConstPointer();
6021   const int *connI=_nodal_connec_index->getConstPointer();
6022   const double *coo=_coords->getConstPointer();
6023   double tmp[12];
6024   for(int i=0;i<nbOfCells;i++,pt++)
6025     {
6026       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6027       switch(t)
6028         {
6029           case INTERP_KERNEL::NORM_TRI3:
6030             {
6031               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6032               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6033               break;
6034             }
6035           case INTERP_KERNEL::NORM_QUAD4:
6036             {
6037               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6038               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6039               break;
6040             }
6041           case INTERP_KERNEL::NORM_TETRA4:
6042             {
6043               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6044               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6045               break;
6046             }
6047         default:
6048           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6049         }
6050       conn+=connI[i+1]-connI[i];
6051     }
6052   ret->setName("AspectRatio");
6053   ret->synchronizeTimeWithSupport();
6054   return ret.retn();
6055 }
6056
6057 /*!
6058  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6059  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6060  * treated: INTERP_KERNEL::NORM_QUAD4.
6061  * For a cell of other type an exception is thrown.
6062  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6063  *          cells and one time, lying on \a this mesh. The caller is to delete this
6064  *          field using decrRef() as it is no more needed. 
6065  *  \throw If the coordinates array is not set.
6066  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6067  *  \throw If the connectivity data array has more than one component.
6068  *  \throw If the connectivity data array has a named component.
6069  *  \throw If the connectivity index data array has more than one component.
6070  *  \throw If the connectivity index data array has a named component.
6071  *  \throw If \a this->getMeshDimension() != 2.
6072  *  \throw If \a this->getSpaceDimension() != 3.
6073  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6074  */
6075 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6076 {
6077   checkCoherency();
6078   int spaceDim=getSpaceDimension();
6079   int meshDim=getMeshDimension();
6080   if(spaceDim!=3)
6081     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6082   if(meshDim!=2)
6083     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6084   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6085   ret->setMesh(this);
6086   int nbOfCells=getNumberOfCells();
6087   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6088   arr->alloc(nbOfCells,1);
6089   double *pt=arr->getPointer();
6090   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6091   const int *conn=_nodal_connec->getConstPointer();
6092   const int *connI=_nodal_connec_index->getConstPointer();
6093   const double *coo=_coords->getConstPointer();
6094   double tmp[12];
6095   for(int i=0;i<nbOfCells;i++,pt++)
6096     {
6097       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6098       switch(t)
6099         {
6100           case INTERP_KERNEL::NORM_QUAD4:
6101             {
6102               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6103               *pt=INTERP_KERNEL::quadWarp(tmp);
6104               break;
6105             }
6106         default:
6107           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6108         }
6109       conn+=connI[i+1]-connI[i];
6110     }
6111   ret->setName("Warp");
6112   ret->synchronizeTimeWithSupport();
6113   return ret.retn();
6114 }
6115
6116
6117 /*!
6118  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6119  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6120  * treated: INTERP_KERNEL::NORM_QUAD4.
6121  * For a cell of other type an exception is thrown.
6122  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6123  *          cells and one time, lying on \a this mesh. The caller is to delete this
6124  *          field using decrRef() as it is no more needed. 
6125  *  \throw If the coordinates array is not set.
6126  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6127  *  \throw If the connectivity data array has more than one component.
6128  *  \throw If the connectivity data array has a named component.
6129  *  \throw If the connectivity index data array has more than one component.
6130  *  \throw If the connectivity index data array has a named component.
6131  *  \throw If \a this->getMeshDimension() != 2.
6132  *  \throw If \a this->getSpaceDimension() != 3.
6133  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6134  */
6135 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6136 {
6137   checkCoherency();
6138   int spaceDim=getSpaceDimension();
6139   int meshDim=getMeshDimension();
6140   if(spaceDim!=3)
6141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6142   if(meshDim!=2)
6143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6144   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6145   ret->setMesh(this);
6146   int nbOfCells=getNumberOfCells();
6147   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6148   arr->alloc(nbOfCells,1);
6149   double *pt=arr->getPointer();
6150   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6151   const int *conn=_nodal_connec->getConstPointer();
6152   const int *connI=_nodal_connec_index->getConstPointer();
6153   const double *coo=_coords->getConstPointer();
6154   double tmp[12];
6155   for(int i=0;i<nbOfCells;i++,pt++)
6156     {
6157       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6158       switch(t)
6159         {
6160           case INTERP_KERNEL::NORM_QUAD4:
6161             {
6162               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6163               *pt=INTERP_KERNEL::quadSkew(tmp);
6164               break;
6165             }
6166         default:
6167           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6168         }
6169       conn+=connI[i+1]-connI[i];
6170     }
6171   ret->setName("Skew");
6172   ret->synchronizeTimeWithSupport();
6173   return ret.retn();
6174 }
6175
6176 /*!
6177  * This method aggregate the bbox of each cell and put it into bbox parameter.
6178  * 
6179  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6180  * 
6181  * \throw If \a this is not fully set (coordinates and connectivity).
6182  * \throw If a cell in \a this has no valid nodeId.
6183  */
6184 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6185 {
6186   checkFullyDefined();
6187   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6188   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6189   double *bbox(ret->getPointer());
6190   for(int i=0;i<nbOfCells*spaceDim;i++)
6191     {
6192       bbox[2*i]=std::numeric_limits<double>::max();
6193       bbox[2*i+1]=-std::numeric_limits<double>::max();
6194     }
6195   const double *coordsPtr(_coords->getConstPointer());
6196   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6197   for(int i=0;i<nbOfCells;i++)
6198     {
6199       int offset=connI[i]+1;
6200       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6201       for(int j=0;j<nbOfNodesForCell;j++)
6202         {
6203           int nodeId=conn[offset+j];
6204           if(nodeId>=0 && nodeId<nbOfNodes)
6205             {
6206               for(int k=0;k<spaceDim;k++)
6207                 {
6208                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6209                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6210                 }
6211               kk++;
6212             }
6213         }
6214       if(kk==0)
6215         {
6216           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6217           throw INTERP_KERNEL::Exception(oss.str().c_str());
6218         }
6219     }
6220   return ret.retn();
6221 }
6222
6223 /// @cond INTERNAL
6224
6225 namespace ParaMEDMEMImpl
6226 {
6227   class ConnReader
6228   {
6229   public:
6230     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6231     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6232   private:
6233     const int *_conn;
6234     int _val;
6235   };
6236
6237   class ConnReader2
6238   {
6239   public:
6240     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6241     bool operator() (const int& pos) { return _conn[pos]==_val; }
6242   private:
6243     const int *_conn;
6244     int _val;
6245   };
6246 }
6247
6248 /// @endcond
6249
6250 /*!
6251  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6252  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6253  * \a this is composed in cell types.
6254  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6255  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6256  * This parameter is kept only for compatibility with other methode listed above.
6257  */
6258 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6259 {
6260   checkConnectivityFullyDefined();
6261   const int *conn=_nodal_connec->getConstPointer();
6262   const int *connI=_nodal_connec_index->getConstPointer();
6263   const int *work=connI;
6264   int nbOfCells=getNumberOfCells();
6265   std::size_t n=getAllTypes().size();
6266   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6267   std::set<INTERP_KERNEL::NormalizedCellType> types;
6268   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6269     {
6270       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6271       if(types.find(typ)!=types.end())
6272         {
6273           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6274           oss << " is not contiguous !";
6275           throw INTERP_KERNEL::Exception(oss.str().c_str());
6276         }
6277       types.insert(typ);
6278       ret[3*i]=typ;
6279       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6280       ret[3*i+1]=(int)std::distance(work,work2);
6281       work=work2;
6282     }
6283   return ret;
6284 }
6285
6286 /*!
6287  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6288  * only for types cell, type node is not managed.
6289  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6290  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6291  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6292  * If 2 or more same geometric type is in \a code and exception is thrown too.
6293  *
6294  * This method firstly checks
6295  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6296  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6297  * an exception is thrown too.
6298  * 
6299  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6300  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6301  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6302  */
6303 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6304 {
6305   if(code.empty())
6306     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6307   std::size_t sz=code.size();
6308   std::size_t n=sz/3;
6309   if(sz%3!=0)
6310     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6311   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6312   int nb=0;
6313   bool isNoPflUsed=true;
6314   for(std::size_t i=0;i<n;i++)
6315     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6316       {
6317         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6318         nb+=code[3*i+1];
6319         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6320           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6321         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6322       }
6323   if(types.size()!=n)
6324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6325   if(isNoPflUsed)
6326     {
6327       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6328         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6329       if(types.size()==_types.size())
6330         return 0;
6331     }
6332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6333   ret->alloc(nb,1);
6334   int *retPtr=ret->getPointer();
6335   const int *connI=_nodal_connec_index->getConstPointer();
6336   const int *conn=_nodal_connec->getConstPointer();
6337   int nbOfCells=getNumberOfCells();
6338   const int *i=connI;
6339   int kk=0;
6340   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6341     {
6342       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6343       int offset=(int)std::distance(connI,i);
6344       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6345       int nbOfCellsOfCurType=(int)std::distance(i,j);
6346       if(code[3*kk+2]==-1)
6347         for(int k=0;k<nbOfCellsOfCurType;k++)
6348           *retPtr++=k+offset;
6349       else
6350         {
6351           int idInIdsPerType=code[3*kk+2];
6352           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6353             {
6354               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6355               if(zePfl)
6356                 {
6357                   zePfl->checkAllocated();
6358                   if(zePfl->getNumberOfComponents()==1)
6359                     {
6360                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6361                         {
6362                           if(*k>=0 && *k<nbOfCellsOfCurType)
6363                             *retPtr=(*k)+offset;
6364                           else
6365                             {
6366                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6367                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6368                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6369                             }
6370                         }
6371                     }
6372                   else
6373                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6374                 }
6375               else
6376                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6377             }
6378           else
6379             {
6380               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6381               oss << " should be in [0," << idsPerType.size() << ") !";
6382               throw INTERP_KERNEL::Exception(oss.str().c_str());
6383             }
6384         }
6385       i=j;
6386     }
6387   return ret.retn();
6388 }
6389
6390 /*!
6391  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6392  * 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.
6393  * 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.
6394  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6395  * 
6396  * \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.
6397  * \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,
6398  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6399  * \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.
6400  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6401  * \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
6402  */
6403 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6404 {
6405   if(!profile)
6406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6407   if(profile->getNumberOfComponents()!=1)
6408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6409   checkConnectivityFullyDefined();
6410   const int *conn=_nodal_connec->getConstPointer();
6411   const int *connI=_nodal_connec_index->getConstPointer();
6412   int nbOfCells=getNumberOfCells();
6413   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6414   std::vector<int> typeRangeVals(1);
6415   for(const int *i=connI;i!=connI+nbOfCells;)
6416     {
6417       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6418       if(std::find(types.begin(),types.end(),curType)!=types.end())
6419         {
6420           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6421         }
6422       types.push_back(curType);
6423       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6424       typeRangeVals.push_back((int)std::distance(connI,i));
6425     }
6426   //
6427   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6428   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6432   //
6433   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6434   code.resize(3*nbOfCastsFinal);
6435   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6436   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6437   for(int i=0;i<nbOfCastsFinal;i++)
6438     {
6439       int castId=castsPresent->getIJ(i,0);
6440       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6441       idsInPflPerType2.push_back(tmp3);
6442       code[3*i]=(int)types[castId];
6443       code[3*i+1]=tmp3->getNumberOfTuples();
6444       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6445       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6446         {
6447           tmp4->copyStringInfoFrom(*profile);
6448           idsPerType2.push_back(tmp4);
6449           code[3*i+2]=(int)idsPerType2.size()-1;
6450         }
6451       else
6452         {
6453           code[3*i+2]=-1;
6454         }
6455     }
6456   std::size_t sz2=idsInPflPerType2.size();
6457   idsInPflPerType.resize(sz2);
6458   for(std::size_t i=0;i<sz2;i++)
6459     {
6460       DataArrayInt *locDa=idsInPflPerType2[i];
6461       locDa->incrRef();
6462       idsInPflPerType[i]=locDa;
6463     }
6464   std::size_t sz=idsPerType2.size();
6465   idsPerType.resize(sz);
6466   for(std::size_t i=0;i<sz;i++)
6467     {
6468       DataArrayInt *locDa=idsPerType2[i];
6469       locDa->incrRef();
6470       idsPerType[i]=locDa;
6471     }
6472 }
6473
6474 /*!
6475  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6476  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6477  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6478  * 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.
6479  */
6480 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6481 {
6482   checkFullyDefined();
6483   nM1LevMesh->checkFullyDefined();
6484   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6485     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6486   if(_coords!=nM1LevMesh->getCoords())
6487     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6489   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6490   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6492   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6493   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6494   tmp->setConnectivity(tmp0,tmp1);
6495   tmp->renumberCells(ret0->getConstPointer(),false);
6496   revDesc=tmp->getNodalConnectivity();
6497   revDescIndx=tmp->getNodalConnectivityIndex();
6498   DataArrayInt *ret=0;
6499   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6500     {
6501       int tmp2;
6502       ret->getMaxValue(tmp2);
6503       ret->decrRef();
6504       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6505       throw INTERP_KERNEL::Exception(oss.str().c_str());
6506     }
6507   nM1LevMeshIds=ret;
6508   //
6509   revDesc->incrRef();
6510   revDescIndx->incrRef();
6511   ret1->incrRef();
6512   ret0->incrRef();
6513   meshnM1Old2New=ret0;
6514   return ret1;
6515 }
6516
6517 /*!
6518  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6519  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6520  * in "Old to New" mode.
6521  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6522  *          this array using decrRef() as it is no more needed.
6523  *  \throw If the nodal connectivity of cells is not defined.
6524  */
6525 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6526 {
6527   checkConnectivityFullyDefined();
6528   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6529   renumberCells(ret->getConstPointer(),false);
6530   return ret.retn();
6531 }
6532
6533 /*!
6534  * This methods checks that cells are sorted by their types.
6535  * This method makes asumption (no check) that connectivity is correctly set before calling.
6536  */
6537 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6538 {
6539   checkFullyDefined();
6540   const int *conn=_nodal_connec->getConstPointer();
6541   const int *connI=_nodal_connec_index->getConstPointer();
6542   int nbOfCells=getNumberOfCells();
6543   std::set<INTERP_KERNEL::NormalizedCellType> types;
6544   for(const int *i=connI;i!=connI+nbOfCells;)
6545     {
6546       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6547       if(types.find(curType)!=types.end())
6548         return false;
6549       types.insert(curType);
6550       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6551     }
6552   return true;
6553 }
6554
6555 /*!
6556  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6557  * The geometric type order is specified by MED file.
6558  * 
6559  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6560  */
6561 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6562 {
6563   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6564 }
6565
6566 /*!
6567  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6568  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6569  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6570  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6571  */
6572 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6573 {
6574   checkFullyDefined();
6575   const int *conn=_nodal_connec->getConstPointer();
6576   const int *connI=_nodal_connec_index->getConstPointer();
6577   int nbOfCells=getNumberOfCells();
6578   if(nbOfCells==0)
6579     return true;
6580   int lastPos=-1;
6581   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6582   for(const int *i=connI;i!=connI+nbOfCells;)
6583     {
6584       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6585       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6586       if(isTypeExists!=orderEnd)
6587         {
6588           int pos=(int)std::distance(orderBg,isTypeExists);
6589           if(pos<=lastPos)
6590             return false;
6591           lastPos=pos;
6592           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6593         }
6594       else
6595         {
6596           if(sg.find(curType)==sg.end())
6597             {
6598               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6599               sg.insert(curType);
6600             }
6601           else
6602             return false;
6603         }
6604     }
6605   return true;
6606 }
6607
6608 /*!
6609  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6610  * 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
6611  * 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'.
6612  */
6613 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6614 {
6615   checkConnectivityFullyDefined();
6616   int nbOfCells=getNumberOfCells();
6617   const int *conn=_nodal_connec->getConstPointer();
6618   const int *connI=_nodal_connec_index->getConstPointer();
6619   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6620   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6621   tmpa->alloc(nbOfCells,1);
6622   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6623   tmpb->fillWithZero();
6624   int *tmp=tmpa->getPointer();
6625   int *tmp2=tmpb->getPointer();
6626   for(const int *i=connI;i!=connI+nbOfCells;i++)
6627     {
6628       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6629       if(where!=orderEnd)
6630         {
6631           int pos=(int)std::distance(orderBg,where);
6632           tmp2[pos]++;
6633           tmp[std::distance(connI,i)]=pos;
6634         }
6635       else
6636         {
6637           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6638           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6639           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6640           throw INTERP_KERNEL::Exception(oss.str().c_str());
6641         }
6642     }
6643   nbPerType=tmpb.retn();
6644   return tmpa.retn();
6645 }
6646
6647 /*!
6648  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6649  *
6650  * \return a new object containing the old to new correspondance.
6651  *
6652  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6653  */
6654 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6655 {
6656   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6657 }
6658
6659 /*!
6660  * 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.
6661  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6662  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6663  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6664  */
6665 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6666 {
6667   DataArrayInt *nbPerType=0;
6668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6669   nbPerType->decrRef();
6670   return tmpa->buildPermArrPerLevel();
6671 }
6672
6673 /*!
6674  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6675  * The number of cells remains unchanged after the call of this method.
6676  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6677  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6678  *
6679  * \return the array giving the correspondance old to new.
6680  */
6681 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6682 {
6683   checkFullyDefined();
6684   computeTypes();
6685   const int *conn=_nodal_connec->getConstPointer();
6686   const int *connI=_nodal_connec_index->getConstPointer();
6687   int nbOfCells=getNumberOfCells();
6688   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6689   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6690     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6691       {
6692         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6693         types.push_back(curType);
6694         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6695       }
6696   DataArrayInt *ret=DataArrayInt::New();
6697   ret->alloc(nbOfCells,1);
6698   int *retPtr=ret->getPointer();
6699   std::fill(retPtr,retPtr+nbOfCells,-1);
6700   int newCellId=0;
6701   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6702     {
6703       for(const int *i=connI;i!=connI+nbOfCells;i++)
6704         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6705           retPtr[std::distance(connI,i)]=newCellId++;
6706     }
6707   renumberCells(retPtr,false);
6708   return ret;
6709 }
6710
6711 /*!
6712  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6713  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6714  * This method makes asumption that connectivity is correctly set before calling.
6715  */
6716 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6717 {
6718   checkConnectivityFullyDefined();
6719   const int *conn=_nodal_connec->getConstPointer();
6720   const int *connI=_nodal_connec_index->getConstPointer();
6721   int nbOfCells=getNumberOfCells();
6722   std::vector<MEDCouplingUMesh *> ret;
6723   for(const int *i=connI;i!=connI+nbOfCells;)
6724     {
6725       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6726       int beginCellId=(int)std::distance(connI,i);
6727       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6728       int endCellId=(int)std::distance(connI,i);
6729       int sz=endCellId-beginCellId;
6730       int *cells=new int[sz];
6731       for(int j=0;j<sz;j++)
6732         cells[j]=beginCellId+j;
6733       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6734       delete [] cells;
6735       ret.push_back(m);
6736     }
6737   return ret;
6738 }
6739
6740 /*!
6741  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6742  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6743  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6744  *
6745  * \return a newly allocated instance, that the caller must manage.
6746  * \throw If \a this contains more than one geometric type.
6747  * \throw If the nodal connectivity of \a this is not fully defined.
6748  * \throw If the internal data is not coherent.
6749  */
6750 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6751 {
6752   checkConnectivityFullyDefined();
6753     if(_types.size()!=1)
6754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6755   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6756   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6757   ret->setCoords(getCoords());
6758   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6759   if(retC)
6760     {
6761       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6762       retC->setNodalConnectivity(c);
6763     }
6764   else
6765     {
6766       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6767       if(!retD)
6768         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6769       DataArrayInt *c=0,*ci=0;
6770       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6771       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6772       retD->setNodalConnectivity(cs,cis);
6773     }
6774   return ret.retn();
6775 }
6776
6777 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6778 {
6779   checkConnectivityFullyDefined();
6780     if(_types.size()!=1)
6781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6782   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6783   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6784   if(cm.isDynamic())
6785     {
6786       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6787       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6788       throw INTERP_KERNEL::Exception(oss.str().c_str());
6789     }
6790   int nbCells=getNumberOfCells();
6791   int typi=(int)typ;
6792   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6794   int *outPtr=connOut->getPointer();
6795   const int *conn=_nodal_connec->begin();
6796   const int *connI=_nodal_connec_index->begin();
6797   nbNodesPerCell++;
6798   for(int i=0;i<nbCells;i++,connI++)
6799     {
6800       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6801         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6802       else
6803         {
6804           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 << ") !";
6805           throw INTERP_KERNEL::Exception(oss.str().c_str());
6806         }
6807     }
6808   return connOut.retn();
6809 }
6810
6811 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6812 {
6813   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6814   checkConnectivityFullyDefined();
6815   if(_types.size()!=1)
6816     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6817   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6818   if(lgth<nbCells)
6819     throw INTERP_KERNEL::Exception(msg0);
6820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6821   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6822   int *cp(c->getPointer()),*cip(ci->getPointer());
6823   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6824   cip[0]=0;
6825   for(int i=0;i<nbCells;i++,cip++,incip++)
6826     {
6827       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6828       int delta(stop-strt);
6829       if(delta>=1)
6830         {
6831           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6832             cp=std::copy(incp+strt,incp+stop,cp);
6833           else
6834             throw INTERP_KERNEL::Exception(msg0);
6835         }
6836       else
6837         throw INTERP_KERNEL::Exception(msg0);
6838       cip[1]=cip[0]+delta;
6839     }
6840   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6841 }
6842
6843 /*!
6844  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6845  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6846  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6847  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6848  * are not used here to avoid the build of big permutation array.
6849  *
6850  * \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
6851  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6852  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6853  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6854  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6855  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6856  * \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
6857  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6858  */
6859 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6860                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6861                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6862 {
6863   std::vector<const MEDCouplingUMesh *> ms2;
6864   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6865     if(*it)
6866       {
6867         (*it)->checkConnectivityFullyDefined();
6868         ms2.push_back(*it);
6869       }
6870   if(ms2.empty())
6871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6872   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6873   int meshDim=ms2[0]->getMeshDimension();
6874   std::vector<const MEDCouplingUMesh *> m1ssm;
6875   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6876   //
6877   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6878   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6879   int fake=0,rk=0;
6880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6881   ret1->alloc(0,1); ret2->alloc(0,1);
6882   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6883     {
6884       if(meshDim!=(*it)->getMeshDimension())
6885         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6886       if(refCoo!=(*it)->getCoords())
6887         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6888       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6889       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6890       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6891       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6892         {
6893           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6894           m1ssmSingleAuto.push_back(singleCell);
6895           m1ssmSingle.push_back(singleCell);
6896           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6897         }
6898     }
6899   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6900   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6901   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6902   for(std::size_t i=0;i<m1ssm.size();i++)
6903     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6904   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6905   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6906   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6907   return ret0.retn();
6908 }
6909
6910 /*!
6911  * This method returns a newly created DataArrayInt instance.
6912  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6913  */
6914 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6915 {
6916   checkFullyDefined();
6917   const int *conn=_nodal_connec->getConstPointer();
6918   const int *connIndex=_nodal_connec_index->getConstPointer();
6919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6920   for(const int *w=begin;w!=end;w++)
6921     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6922       ret->pushBackSilent(*w);
6923   return ret.retn();
6924 }
6925
6926 /*!
6927  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6928  * are in [0:getNumberOfCells())
6929  */
6930 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6931 {
6932   checkFullyDefined();
6933   const int *conn=_nodal_connec->getConstPointer();
6934   const int *connI=_nodal_connec_index->getConstPointer();
6935   int nbOfCells=getNumberOfCells();
6936   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6937   int *tmp=new int[nbOfCells];
6938   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6939     {
6940       int j=0;
6941       for(const int *i=connI;i!=connI+nbOfCells;i++)
6942         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6943           tmp[std::distance(connI,i)]=j++;
6944     }
6945   DataArrayInt *ret=DataArrayInt::New();
6946   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6947   ret->copyStringInfoFrom(*da);
6948   int *retPtr=ret->getPointer();
6949   const int *daPtr=da->getConstPointer();
6950   int nbOfElems=da->getNbOfElems();
6951   for(int k=0;k<nbOfElems;k++)
6952     retPtr[k]=tmp[daPtr[k]];
6953   delete [] tmp;
6954   return ret;
6955 }
6956
6957 /*!
6958  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6959  * This method \b works \b for mesh sorted by type.
6960  * cells whose ids is in 'idsPerGeoType' array.
6961  * This method conserves coords and name of mesh.
6962  */
6963 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6964 {
6965   std::vector<int> code=getDistributionOfTypes();
6966   std::size_t nOfTypesInThis=code.size()/3;
6967   int sz=0,szOfType=0;
6968   for(std::size_t i=0;i<nOfTypesInThis;i++)
6969     {
6970       if(code[3*i]!=type)
6971         sz+=code[3*i+1];
6972       else
6973         szOfType=code[3*i+1];
6974     }
6975   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6976     if(*work<0 || *work>=szOfType)
6977       {
6978         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6979         oss << ". It should be in [0," << szOfType << ") !";
6980         throw INTERP_KERNEL::Exception(oss.str().c_str());
6981       }
6982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6983   int *idsPtr=idsTokeep->getPointer();
6984   int offset=0;
6985   for(std::size_t i=0;i<nOfTypesInThis;i++)
6986     {
6987       if(code[3*i]!=type)
6988         for(int j=0;j<code[3*i+1];j++)
6989           *idsPtr++=offset+j;
6990       else
6991         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6992       offset+=code[3*i+1];
6993     }
6994   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6995   ret->copyTinyInfoFrom(this);
6996   return ret.retn();
6997 }
6998
6999 /*!
7000  * This method returns a vector of size 'this->getNumberOfCells()'.
7001  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7002  */
7003 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7004 {
7005   int ncell=getNumberOfCells();
7006   std::vector<bool> ret(ncell);
7007   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7008   const int *c=getNodalConnectivity()->getConstPointer();
7009   for(int i=0;i<ncell;i++)
7010     {
7011       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7012       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7013       ret[i]=cm.isQuadratic();
7014     }
7015   return ret;
7016 }
7017
7018 /*!
7019  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7020  */
7021 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7022 {
7023   if(other->getType()!=UNSTRUCTURED)
7024     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7025   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7026   return MergeUMeshes(this,otherC);
7027 }
7028
7029 /*!
7030  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7031  * computed by averaging coordinates of cell nodes, so this method is not a right
7032  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7033  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7034  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7035  *          components. The caller is to delete this array using decrRef() as it is
7036  *          no more needed.
7037  *  \throw If the coordinates array is not set.
7038  *  \throw If the nodal connectivity of cells is not defined.
7039  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7040  */
7041 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7042 {
7043   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7044   int spaceDim=getSpaceDimension();
7045   int nbOfCells=getNumberOfCells();
7046   ret->alloc(nbOfCells,spaceDim);
7047   ret->copyStringInfoFrom(*getCoords());
7048   double *ptToFill=ret->getPointer();
7049   const int *nodal=_nodal_connec->getConstPointer();
7050   const int *nodalI=_nodal_connec_index->getConstPointer();
7051   const double *coor=_coords->getConstPointer();
7052   for(int i=0;i<nbOfCells;i++)
7053     {
7054       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7055       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7056       ptToFill+=spaceDim;
7057     }
7058   return ret.retn();
7059 }
7060
7061 /*!
7062  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7063  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7064  * 
7065  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7066  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7067  * 
7068  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7069  * \throw If \a this is not fully defined (coordinates and connectivity)
7070  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7071  */
7072 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7073 {
7074   checkFullyDefined();
7075   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7076   int spaceDim=getSpaceDimension();
7077   int nbOfCells=getNumberOfCells();
7078   int nbOfNodes=getNumberOfNodes();
7079   ret->alloc(nbOfCells,spaceDim);
7080   double *ptToFill=ret->getPointer();
7081   const int *nodal=_nodal_connec->getConstPointer();
7082   const int *nodalI=_nodal_connec_index->getConstPointer();
7083   const double *coor=_coords->getConstPointer();
7084   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7085     {
7086       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7087       std::fill(ptToFill,ptToFill+spaceDim,0.);
7088       if(type!=INTERP_KERNEL::NORM_POLYHED)
7089         {
7090           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7091             {
7092               if(*conn>=0 && *conn<nbOfNodes)
7093                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7094               else
7095                 {
7096                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7097                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7098                 }
7099             }
7100           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7101           if(nbOfNodesInCell>0)
7102             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7103           else
7104             {
7105               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7106               throw INTERP_KERNEL::Exception(oss.str().c_str());
7107             }
7108         }
7109       else
7110         {
7111           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7112           s.erase(-1);
7113           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7114             {
7115               if(*it>=0 && *it<nbOfNodes)
7116                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7117               else
7118                 {
7119                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7120                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7121                 }
7122             }
7123           if(!s.empty())
7124             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7125           else
7126             {
7127               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7128               throw INTERP_KERNEL::Exception(oss.str().c_str());
7129             }
7130         }
7131     }
7132   return ret.retn();
7133 }
7134
7135 /*!
7136  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7137  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7138  * are specified via an array of cell ids. 
7139  *  \warning Validity of the specified cell ids is not checked! 
7140  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7141  *  \param [in] begin - an array of cell ids of interest.
7142  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7143  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7144  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7145  *          caller is to delete this array using decrRef() as it is no more needed. 
7146  *  \throw If the coordinates array is not set.
7147  *  \throw If the nodal connectivity of cells is not defined.
7148  *
7149  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7150  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7151  */
7152 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7153 {
7154   DataArrayDouble *ret=DataArrayDouble::New();
7155   int spaceDim=getSpaceDimension();
7156   int nbOfTuple=(int)std::distance(begin,end);
7157   ret->alloc(nbOfTuple,spaceDim);
7158   double *ptToFill=ret->getPointer();
7159   double *tmp=new double[spaceDim];
7160   const int *nodal=_nodal_connec->getConstPointer();
7161   const int *nodalI=_nodal_connec_index->getConstPointer();
7162   const double *coor=_coords->getConstPointer();
7163   for(const int *w=begin;w!=end;w++)
7164     {
7165       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7166       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7167       ptToFill+=spaceDim;
7168     }
7169   delete [] tmp;
7170   return ret;
7171 }
7172
7173 /*!
7174  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7175  * 
7176  */
7177 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7178 {
7179   if(!da)
7180     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7181   da->checkAllocated();
7182   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7183   ret->setCoords(da);
7184   int nbOfTuples=da->getNumberOfTuples();
7185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7187   c->alloc(2*nbOfTuples,1);
7188   cI->alloc(nbOfTuples+1,1);
7189   int *cp=c->getPointer();
7190   int *cip=cI->getPointer();
7191   *cip++=0;
7192   for(int i=0;i<nbOfTuples;i++)
7193     {
7194       *cp++=INTERP_KERNEL::NORM_POINT1;
7195       *cp++=i;
7196       *cip++=2*(i+1);
7197     }
7198   ret->setConnectivity(c,cI,true);
7199   return ret.retn();
7200 }
7201 /*!
7202  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7203  * Cells and nodes of
7204  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7205  *  \param [in] mesh1 - the first mesh.
7206  *  \param [in] mesh2 - the second mesh.
7207  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7208  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7209  *          is no more needed.
7210  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7211  *  \throw If the coordinates array is not set in none of the meshes.
7212  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7213  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7214  */
7215 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7216 {
7217   std::vector<const MEDCouplingUMesh *> tmp(2);
7218   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7219   return MergeUMeshes(tmp);
7220 }
7221
7222 /*!
7223  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7224  * Cells and nodes of
7225  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7226  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7227  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7228  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7229  *          is no more needed.
7230  *  \throw If \a a.size() == 0.
7231  *  \throw If \a a[ *i* ] == NULL.
7232  *  \throw If the coordinates array is not set in none of the meshes.
7233  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7234  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7235 */
7236 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7237 {
7238   std::size_t sz=a.size();
7239   if(sz==0)
7240     return MergeUMeshesLL(a);
7241   for(std::size_t ii=0;ii<sz;ii++)
7242     if(!a[ii])
7243       {
7244         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7245         throw INTERP_KERNEL::Exception(oss.str().c_str());
7246       }
7247   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7248   std::vector< const MEDCouplingUMesh * > aa(sz);
7249   int spaceDim=-3;
7250   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7251     {
7252       const MEDCouplingUMesh *cur=a[i];
7253       const DataArrayDouble *coo=cur->getCoords();
7254       if(coo)
7255         spaceDim=coo->getNumberOfComponents();
7256     }
7257   if(spaceDim==-3)
7258     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7259   for(std::size_t i=0;i<sz;i++)
7260     {
7261       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7262       aa[i]=bb[i];
7263     }
7264   return MergeUMeshesLL(aa);
7265 }
7266
7267 /// @cond INTERNAL
7268
7269 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7270 {
7271   if(a.empty())
7272     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7273   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7274   int meshDim=(*it)->getMeshDimension();
7275   int nbOfCells=(*it)->getNumberOfCells();
7276   int meshLgth=(*it++)->getMeshLength();
7277   for(;it!=a.end();it++)
7278     {
7279       if(meshDim!=(*it)->getMeshDimension())
7280         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7281       nbOfCells+=(*it)->getNumberOfCells();
7282       meshLgth+=(*it)->getMeshLength();
7283     }
7284   std::vector<const MEDCouplingPointSet *> aps(a.size());
7285   std::copy(a.begin(),a.end(),aps.begin());
7286   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7287   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7288   ret->setCoords(pts);
7289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7290   c->alloc(meshLgth,1);
7291   int *cPtr=c->getPointer();
7292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7293   cI->alloc(nbOfCells+1,1);
7294   int *cIPtr=cI->getPointer();
7295   *cIPtr++=0;
7296   int offset=0;
7297   int offset2=0;
7298   for(it=a.begin();it!=a.end();it++)
7299     {
7300       int curNbOfCell=(*it)->getNumberOfCells();
7301       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7302       const int *curC=(*it)->_nodal_connec->getConstPointer();
7303       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7304       for(int j=0;j<curNbOfCell;j++)
7305         {
7306           const int *src=curC+curCI[j];
7307           *cPtr++=*src++;
7308           for(;src!=curC+curCI[j+1];src++,cPtr++)
7309             {
7310               if(*src!=-1)
7311                 *cPtr=*src+offset2;
7312               else
7313                 *cPtr=-1;
7314             }
7315         }
7316       offset+=curCI[curNbOfCell];
7317       offset2+=(*it)->getNumberOfNodes();
7318     }
7319   //
7320   ret->setConnectivity(c,cI,true);
7321   return ret.retn();
7322 }
7323
7324 /// @endcond
7325
7326 /*!
7327  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7328  * dimension and sharing the node coordinates array.
7329  * All cells of the first mesh precede all cells of the second mesh
7330  * within the result mesh. 
7331  *  \param [in] mesh1 - the first mesh.
7332  *  \param [in] mesh2 - the second mesh.
7333  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7334  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7335  *          is no more needed.
7336  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7337  *  \throw If the meshes do not share the node coordinates array.
7338  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7339  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7340  */
7341 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7342 {
7343   std::vector<const MEDCouplingUMesh *> tmp(2);
7344   tmp[0]=mesh1; tmp[1]=mesh2;
7345   return MergeUMeshesOnSameCoords(tmp);
7346 }
7347
7348 /*!
7349  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7350  * dimension and sharing the node coordinates array.
7351  * All cells of the *i*-th mesh precede all cells of the
7352  * (*i*+1)-th mesh within the result mesh.
7353  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7354  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7355  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7356  *          is no more needed.
7357  *  \throw If \a a.size() == 0.
7358  *  \throw If \a a[ *i* ] == NULL.
7359  *  \throw If the meshes do not share the node coordinates array.
7360  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7361  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7362  */
7363 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7364 {
7365   if(meshes.empty())
7366     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7367   for(std::size_t ii=0;ii<meshes.size();ii++)
7368     if(!meshes[ii])
7369       {
7370         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7371         throw INTERP_KERNEL::Exception(oss.str().c_str());
7372       }
7373   const DataArrayDouble *coords=meshes.front()->getCoords();
7374   int meshDim=meshes.front()->getMeshDimension();
7375   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7376   int meshLgth=0;
7377   int meshIndexLgth=0;
7378   for(;iter!=meshes.end();iter++)
7379     {
7380       if(coords!=(*iter)->getCoords())
7381         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7382       if(meshDim!=(*iter)->getMeshDimension())
7383         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7384       meshLgth+=(*iter)->getMeshLength();
7385       meshIndexLgth+=(*iter)->getNumberOfCells();
7386     }
7387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7388   nodal->alloc(meshLgth,1);
7389   int *nodalPtr=nodal->getPointer();
7390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7391   nodalIndex->alloc(meshIndexLgth+1,1);
7392   int *nodalIndexPtr=nodalIndex->getPointer();
7393   int offset=0;
7394   for(iter=meshes.begin();iter!=meshes.end();iter++)
7395     {
7396       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7397       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7398       int nbOfCells=(*iter)->getNumberOfCells();
7399       int meshLgth2=(*iter)->getMeshLength();
7400       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7401       if(iter!=meshes.begin())
7402         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7403       else
7404         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7405       offset+=meshLgth2;
7406     }
7407   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7408   ret->setName("merge");
7409   ret->setMeshDimension(meshDim);
7410   ret->setConnectivity(nodal,nodalIndex,true);
7411   ret->setCoords(coords);
7412   return ret;
7413 }
7414
7415 /*!
7416  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7417  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7418  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7419  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7420  * New" mode are returned for each input mesh.
7421  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7422  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7423  *          valid values [0,1,2], see zipConnectivityTraducer().
7424  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7425  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7426  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7427  *          no more needed.
7428  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7429  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7430  *          is no more needed.
7431  *  \throw If \a meshes.size() == 0.
7432  *  \throw If \a meshes[ *i* ] == NULL.
7433  *  \throw If the meshes do not share the node coordinates array.
7434  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7435  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7436  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7437  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7438  */
7439 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7440 {
7441   //All checks are delegated to MergeUMeshesOnSameCoords
7442   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7443   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7444   corr.resize(meshes.size());
7445   std::size_t nbOfMeshes=meshes.size();
7446   int offset=0;
7447   const int *o2nPtr=o2n->getConstPointer();
7448   for(std::size_t i=0;i<nbOfMeshes;i++)
7449     {
7450       DataArrayInt *tmp=DataArrayInt::New();
7451       int curNbOfCells=meshes[i]->getNumberOfCells();
7452       tmp->alloc(curNbOfCells,1);
7453       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7454       offset+=curNbOfCells;
7455       tmp->setName(meshes[i]->getName().c_str());
7456       corr[i]=tmp;
7457     }
7458   return ret.retn();
7459 }
7460
7461 /*!
7462  * Makes all given meshes share the nodal connectivity array. The common connectivity
7463  * array is created by concatenating the connectivity arrays of all given meshes. All
7464  * the given meshes must be of the same space dimension but dimension of cells **can
7465  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7466  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7467  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7468  *  \param [in,out] meshes - a vector of meshes to update.
7469  *  \throw If any of \a meshes is NULL.
7470  *  \throw If the coordinates array is not set in any of \a meshes.
7471  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7472  *  \throw If \a meshes are of different space dimension.
7473  */
7474 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7475 {
7476   std::size_t sz=meshes.size();
7477   if(sz==0 || sz==1)
7478     return;
7479   std::vector< const DataArrayDouble * > coords(meshes.size());
7480   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7481   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7482     {
7483       if((*it))
7484         {
7485           (*it)->checkConnectivityFullyDefined();
7486           const DataArrayDouble *coo=(*it)->getCoords();
7487           if(coo)
7488             *it2=coo;
7489           else
7490             {
7491               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7492               oss << " has no coordinate array defined !";
7493               throw INTERP_KERNEL::Exception(oss.str().c_str());
7494             }
7495         }
7496       else
7497         {
7498           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7499           oss << " is null !";
7500           throw INTERP_KERNEL::Exception(oss.str().c_str());
7501         }
7502     }
7503   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7504   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7505   int offset=(*it)->getNumberOfNodes();
7506   (*it++)->setCoords(res);
7507   for(;it!=meshes.end();it++)
7508     {
7509       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7510       (*it)->setCoords(res);
7511       (*it)->shiftNodeNumbersInConn(offset);
7512       offset+=oldNumberOfNodes;
7513     }
7514 }
7515
7516 /*!
7517  * Merges nodes coincident with a given precision within all given meshes that share
7518  * the nodal connectivity array. The given meshes **can be of different** mesh
7519  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7520  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7521  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7522  *  \param [in,out] meshes - a vector of meshes to update.
7523  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7524  *  \throw If any of \a meshes is NULL.
7525  *  \throw If the \a meshes do not share the same node coordinates array.
7526  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7527  */
7528 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7529 {
7530   if(meshes.empty())
7531     return ;
7532   std::set<const DataArrayDouble *> s;
7533   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7534     {
7535       if(*it)
7536         s.insert((*it)->getCoords());
7537       else
7538         {
7539           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 !";
7540           throw INTERP_KERNEL::Exception(oss.str().c_str());
7541         }
7542     }
7543   if(s.size()!=1)
7544     {
7545       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 !";
7546       throw INTERP_KERNEL::Exception(oss.str().c_str());
7547     }
7548   const DataArrayDouble *coo=*(s.begin());
7549   if(!coo)
7550     return;
7551   //
7552   DataArrayInt *comm,*commI;
7553   coo->findCommonTuples(eps,-1,comm,commI);
7554   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7555   int oldNbOfNodes=coo->getNumberOfTuples();
7556   int newNbOfNodes;
7557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7558   if(oldNbOfNodes==newNbOfNodes)
7559     return ;
7560   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7561   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7562     {
7563       (*it)->renumberNodesInConn(o2n->getConstPointer());
7564       (*it)->setCoords(newCoords);
7565     } 
7566 }
7567
7568 /*!
7569  * 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.
7570  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7571  * \param isQuad specifies the policy of connectivity.
7572  * @ret in/out parameter in which the result will be append
7573  */
7574 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7575 {
7576   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7577   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7578   ret.push_back(cm.getExtrudedType());
7579   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7580   switch(flatType)
7581     {
7582     case INTERP_KERNEL::NORM_POINT1:
7583       {
7584         ret.push_back(connBg[1]);
7585         ret.push_back(connBg[1]+nbOfNodesPerLev);
7586         break;
7587       }
7588     case INTERP_KERNEL::NORM_SEG2:
7589       {
7590         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7591         ret.insert(ret.end(),conn,conn+4);
7592         break;
7593       }
7594     case INTERP_KERNEL::NORM_SEG3:
7595       {
7596         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7597         ret.insert(ret.end(),conn,conn+8);
7598         break;
7599       }
7600     case INTERP_KERNEL::NORM_QUAD4:
7601       {
7602         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7603         ret.insert(ret.end(),conn,conn+8);
7604         break;
7605       }
7606     case INTERP_KERNEL::NORM_TRI3:
7607       {
7608         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7609         ret.insert(ret.end(),conn,conn+6);
7610         break;
7611       }
7612     case INTERP_KERNEL::NORM_TRI6:
7613       {
7614         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,
7615                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7616         ret.insert(ret.end(),conn,conn+15);
7617         break;
7618       }
7619     case INTERP_KERNEL::NORM_QUAD8:
7620       {
7621         int conn[20]={
7622           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7623           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7624           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7625         };
7626         ret.insert(ret.end(),conn,conn+20);
7627         break;
7628       }
7629     case INTERP_KERNEL::NORM_POLYGON:
7630       {
7631         std::back_insert_iterator< std::vector<int> > ii(ret);
7632         std::copy(connBg+1,connEnd,ii);
7633         *ii++=-1;
7634         std::reverse_iterator<const int *> rConnBg(connEnd);
7635         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7636         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7637         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7638         for(std::size_t i=0;i<nbOfRadFaces;i++)
7639           {
7640             *ii++=-1;
7641             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7642             std::copy(conn,conn+4,ii);
7643           }
7644         break;
7645       }
7646     default:
7647       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7648     }
7649 }
7650
7651 /*!
7652  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7653  */
7654 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7655 {
7656   double v[3]={0.,0.,0.};
7657   std::size_t sz=std::distance(begin,end);
7658   if(isQuadratic)
7659     sz/=2;
7660   for(std::size_t i=0;i<sz;i++)
7661     {
7662       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];
7663       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7664       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7665     }
7666   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7667 }
7668
7669 /*!
7670  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7671  */
7672 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7673 {
7674   std::vector<std::pair<int,int> > edges;
7675   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7676   const int *bgFace=begin;
7677   for(std::size_t i=0;i<nbOfFaces;i++)
7678     {
7679       const int *endFace=std::find(bgFace+1,end,-1);
7680       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7681       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7682         {
7683           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7684           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7685             return false;
7686           edges.push_back(p1);
7687         }
7688       bgFace=endFace+1;
7689     }
7690   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7691 }
7692
7693 /*!
7694  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7695  */
7696 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7697 {
7698   double vec0[3],vec1[3];
7699   std::size_t sz=std::distance(begin,end);
7700   if(sz%2!=0)
7701     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7702   int nbOfNodes=(int)sz/2;
7703   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7704   const double *pt0=coords+3*begin[0];
7705   const double *pt1=coords+3*begin[nbOfNodes];
7706   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7707   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7708 }
7709
7710 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7711 {
7712   std::size_t sz=std::distance(begin,end);
7713   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7714   std::size_t nbOfNodes(sz/2);
7715   std::copy(begin,end,(int *)tmp);
7716   for(std::size_t j=1;j<nbOfNodes;j++)
7717     {
7718       begin[j]=tmp[nbOfNodes-j];
7719       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7720     }
7721 }
7722
7723 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7724 {
7725   std::size_t sz=std::distance(begin,end);
7726   if(sz!=4)
7727     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7728   double vec0[3],vec1[3];
7729   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7730   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]; 
7731   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;
7732 }
7733
7734 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7735 {
7736   std::size_t sz=std::distance(begin,end);
7737   if(sz!=5)
7738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7739   double vec0[3];
7740   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7741   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7742   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7743 }
7744
7745 /*!
7746  * 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 ) 
7747  * 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
7748  * a 2D space.
7749  *
7750  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7751  * \param [in] coords the coordinates with nb of components exactly equal to 3
7752  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7753  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7754  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7755  */
7756 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7757 {
7758   int nbFaces=std::count(begin+1,end,-1)+1;
7759   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7760   double *vPtr=v->getPointer();
7761   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7762   double *pPtr=p->getPointer();
7763   const int *stFaceConn=begin+1;
7764   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7765     {
7766       const int *endFaceConn=std::find(stFaceConn,end,-1);
7767       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7768       stFaceConn=endFaceConn+1;
7769     }
7770   pPtr=p->getPointer(); vPtr=v->getPointer();
7771   DataArrayInt *comm1=0,*commI1=0;
7772   v->findCommonTuples(eps,-1,comm1,commI1);
7773   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7774   const int *comm1Ptr=comm1->getConstPointer();
7775   const int *commI1Ptr=commI1->getConstPointer();
7776   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7777   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7778   //
7779   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7780   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7781   mm->finishInsertingCells();
7782   //
7783   for(int i=0;i<nbOfGrps1;i++)
7784     {
7785       int vecId=comm1Ptr[commI1Ptr[i]];
7786       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7787       DataArrayInt *comm2=0,*commI2=0;
7788       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7789       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7790       const int *comm2Ptr=comm2->getConstPointer();
7791       const int *commI2Ptr=commI2->getConstPointer();
7792       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7793       for(int j=0;j<nbOfGrps2;j++)
7794         {
7795           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7796             {
7797               res->insertAtTheEnd(begin,end);
7798               res->pushBackSilent(-1);
7799             }
7800           else
7801             {
7802               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7803               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7804               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7805               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7806               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7807               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7808               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7809               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7810               const int *idsNodePtr=idsNode->getConstPointer();
7811               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];
7812               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7813               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7814               if(std::abs(norm)>eps)
7815                 {
7816                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7817                   mm3->rotate(center,vec,angle);
7818                 }
7819               mm3->changeSpaceDimension(2);
7820               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7821               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7822               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7823               int nbOfCells=mm4->getNumberOfCells();
7824               for(int k=0;k<nbOfCells;k++)
7825                 {
7826                   int l=0;
7827                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7828                     res->pushBackSilent(idsNodePtr[*work]);
7829                   res->pushBackSilent(-1);
7830                 }
7831             }
7832         }
7833     }
7834   res->popBackSilent();
7835 }
7836
7837 /*!
7838  * 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
7839  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7840  * 
7841  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7842  * \param [in] coords coordinates expected to have 3 components.
7843  * \param [in] begin start of the nodal connectivity of the face.
7844  * \param [in] end end of the nodal connectivity (excluded) of the face.
7845  * \param [out] v the normalized vector of size 3
7846  * \param [out] p the pos of plane
7847  */
7848 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7849 {
7850   std::size_t nbPoints=std::distance(begin,end);
7851   if(nbPoints<3)
7852     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7853   double vec[3]={0.,0.,0.};
7854   std::size_t j=0;
7855   bool refFound=false;
7856   for(;j<nbPoints-1 && !refFound;j++)
7857     {
7858       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7859       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7860       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7861       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7862       if(norm>eps)
7863         {
7864           refFound=true;
7865           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7866         }
7867     }
7868   for(std::size_t i=j;i<nbPoints-1;i++)
7869     {
7870       double curVec[3];
7871       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7872       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7873       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7874       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7875       if(norm<eps)
7876         continue;
7877       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7878       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];
7879       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7880       if(norm>eps)
7881         {
7882           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7883           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7884           return ;
7885         }
7886     }
7887   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7888 }
7889
7890 /*!
7891  * This method tries to obtain a well oriented polyhedron.
7892  * If the algorithm fails, an exception will be thrown.
7893  */
7894 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7895 {
7896   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7897   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7898   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7899   isPerm[0]=true;
7900   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7901   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7902   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7903   //
7904   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7905     {
7906       bgFace=begin;
7907       std::size_t smthChanged=0;
7908       for(std::size_t i=0;i<nbOfFaces;i++)
7909         {
7910           endFace=std::find(bgFace+1,end,-1);
7911           nbOfEdgesInFace=std::distance(bgFace,endFace);
7912           if(!isPerm[i])
7913             {
7914               bool b;
7915               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7916                 {
7917                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7918                   std::pair<int,int> p2(p1.second,p1.first);
7919                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7920                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7921                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7922                 }
7923               if(isPerm[i])
7924                 { 
7925                   if(!b)
7926                     std::reverse(bgFace+1,endFace);
7927                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7928                     {
7929                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7930                       std::pair<int,int> p2(p1.second,p1.first);
7931                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7932                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7933                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7934                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7935                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7936                       if(it!=edgesOK.end())
7937                         {
7938                           edgesOK.erase(it);
7939                           edgesFinished.push_back(p1);
7940                         }
7941                       else
7942                         edgesOK.push_back(p1);
7943                     }
7944                 }
7945             }
7946           bgFace=endFace+1;
7947         }
7948       if(smthChanged==0)
7949         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7950     }
7951   if(!edgesOK.empty())
7952     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7953   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7954     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7955       bgFace=begin;
7956       for(std::size_t i=0;i<nbOfFaces;i++)
7957         {
7958           endFace=std::find(bgFace+1,end,-1);
7959           std::reverse(bgFace+1,endFace);
7960           bgFace=endFace+1;
7961         }
7962     }
7963 }
7964
7965 /*!
7966  * This method makes the assumption spacedimension == meshdimension == 2.
7967  * This method works only for linear cells.
7968  * 
7969  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7970  */
7971 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7972 {
7973   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7975   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7977   int nbOfNodesExpected=m->getNumberOfNodes();
7978   if(m->getNumberOfCells()!=nbOfNodesExpected)
7979     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7981   const int *n2oPtr=n2o->getConstPointer();
7982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7983   m->getReverseNodalConnectivity(revNodal,revNodalI);
7984   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7985   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7986   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7988   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7989   if(nbOfNodesExpected<1)
7990     return ret.retn();
7991   int prevCell=0;
7992   int prevNode=nodalPtr[nodalIPtr[0]+1];
7993   *work++=n2oPtr[prevNode];
7994   for(int i=1;i<nbOfNodesExpected;i++)
7995     {
7996       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7997         {
7998           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7999           conn.erase(prevNode);
8000           if(conn.size()==1)
8001             {
8002               int curNode=*(conn.begin());
8003               *work++=n2oPtr[curNode];
8004               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8005               shar.erase(prevCell);
8006               if(shar.size()==1)
8007                 {
8008                   prevCell=*(shar.begin());
8009                   prevNode=curNode;
8010                 }
8011               else
8012                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8013             }
8014           else
8015             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8016         }
8017       else
8018         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8019     }
8020   return ret.retn();
8021 }
8022
8023 /*!
8024  * This method makes the assumption spacedimension == meshdimension == 3.
8025  * This method works only for linear cells.
8026  * 
8027  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8028  */
8029 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8030 {
8031   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8032     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8033   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8034   const int *conn=m->getNodalConnectivity()->getConstPointer();
8035   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8036   int nbOfCells=m->getNumberOfCells();
8037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8038   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8039   if(nbOfCells<1)
8040     return ret.retn();
8041   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8042   for(int i=1;i<nbOfCells;i++)
8043     {
8044       *work++=-1;
8045       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8046     }
8047   return ret.retn();
8048 }
8049
8050 /*!
8051  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8052  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8053  */
8054 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8055 {
8056   double *w=zipFrmt;
8057   if(spaceDim==3)
8058     for(int i=0;i<nbOfNodesInCell;i++)
8059       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8060   else if(spaceDim==2)
8061     {
8062       for(int i=0;i<nbOfNodesInCell;i++)
8063         {
8064           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8065           *w++=0.;
8066         }
8067     }
8068   else
8069     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8070 }
8071
8072 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8073 {
8074   int nbOfCells=getNumberOfCells();
8075   if(nbOfCells<=0)
8076     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8077   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};
8078   ofs << "  <" << getVTKDataSetType() << ">\n";
8079   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8080   ofs << "      <PointData>\n" << pointData << std::endl;
8081   ofs << "      </PointData>\n";
8082   ofs << "      <CellData>\n" << cellData << std::endl;
8083   ofs << "      </CellData>\n";
8084   ofs << "      <Points>\n";
8085   if(getSpaceDimension()==3)
8086     _coords->writeVTK(ofs,8,"Points");
8087   else
8088     {
8089       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8090       coo->writeVTK(ofs,8,"Points");
8091     }
8092   ofs << "      </Points>\n";
8093   ofs << "      <Cells>\n";
8094   const int *cPtr=_nodal_connec->getConstPointer();
8095   const int *cIPtr=_nodal_connec_index->getConstPointer();
8096   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8099   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8100   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8101   int szFaceOffsets=0,szConn=0;
8102   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8103     {
8104       *w2=cPtr[cIPtr[i]];
8105       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8106         {
8107           *w1=-1;
8108           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8109           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8110         }
8111       else
8112         {
8113           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8114           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8115           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8116           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8117           w4=std::copy(c.begin(),c.end(),w4);
8118         }
8119     }
8120   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8121   types->writeVTK(ofs,8,"UInt8","types");
8122   offsets->writeVTK(ofs,8,"Int32","offsets");
8123   if(szFaceOffsets!=0)
8124     {//presence of Polyhedra
8125       connectivity->reAlloc(szConn);
8126       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8127       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8128       w1=faces->getPointer();
8129       for(int i=0;i<nbOfCells;i++)
8130         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8131           {
8132             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8133             *w1++=nbFaces;
8134             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8135             for(int j=0;j<nbFaces;j++)
8136               {
8137                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8138                 *w1++=(int)std::distance(w6,w5);
8139                 w1=std::copy(w6,w5,w1);
8140                 w6=w5+1;
8141               }
8142           }
8143       faces->writeVTK(ofs,8,"Int32","faces");
8144     }
8145   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8146   ofs << "      </Cells>\n";
8147   ofs << "    </Piece>\n";
8148   ofs << "  </" << getVTKDataSetType() << ">\n";
8149 }
8150
8151 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8152 {
8153   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8154   if(_mesh_dim==-2)
8155     { stream << " Not set !"; return ; }
8156   stream << " Mesh dimension : " << _mesh_dim << ".";
8157   if(_mesh_dim==-1)
8158     return ;
8159   if(!_coords)
8160     { stream << " No coordinates set !"; return ; }
8161   if(!_coords->isAllocated())
8162     { stream << " Coordinates set but not allocated !"; return ; }
8163   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8164   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8165   if(!_nodal_connec_index)
8166     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8167   if(!_nodal_connec_index->isAllocated())
8168     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8169   int lgth=_nodal_connec_index->getNumberOfTuples();
8170   int cpt=_nodal_connec_index->getNumberOfComponents();
8171   if(cpt!=1 || lgth<1)
8172     return ;
8173   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8174 }
8175
8176 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8177 {
8178   return std::string("UnstructuredGrid");
8179 }
8180
8181 /*!
8182  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8183  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8184  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8185  * meshes.
8186  *  \param [in] m1 - the first input mesh which is a partitioned object.
8187  *  \param [in] m2 - the second input mesh which is a partition tool.
8188  *  \param [in] eps - precision used to detect coincident mesh entities.
8189  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8190  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8191  *         this array using decrRef() as it is no more needed.
8192  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8193  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8194  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8195  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8196  *         it is no more needed.  
8197  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8198  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8199  *         is no more needed.  
8200  *  \throw If the coordinates array is not set in any of the meshes.
8201  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8202  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8203  */
8204 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8205 {
8206   m1->checkFullyDefined();
8207   m2->checkFullyDefined();
8208   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8210   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8211   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8212   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8213   std::vector<double> addCoo,addCoordsQuadratic;
8214   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8215   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8216   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8217                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8218   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8220   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8221   std::vector< std::vector<int> > intersectEdge2;
8222   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8223   subDiv2.clear(); dd5=0; dd6=0;
8224   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8225   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8226   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8227                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8228   //
8229   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8230   addCooDa->alloc((int)(addCoo.size())/2,2);
8231   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8232   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8233   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8234   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8235   std::vector<const DataArrayDouble *> coordss(4);
8236   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8237   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8238   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8243   ret->setConnectivity(conn,connI,true);
8244   ret->setCoords(coo);
8245   cellNb1=c1.retn(); cellNb2=c2.retn();
8246   return ret.retn();
8247 }
8248
8249 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8250                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8251                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8252                                                          const std::vector<double>& addCoords,
8253                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8254 {
8255   static const int SPACEDIM=2;
8256   const double *coo1=m1->getCoords()->getConstPointer();
8257   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8258   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8259   int offset1=m1->getNumberOfNodes();
8260   const double *coo2=m2->getCoords()->getConstPointer();
8261   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8262   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8263   int offset2=offset1+m2->getNumberOfNodes();
8264   int offset3=offset2+((int)addCoords.size())/2;
8265   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8266   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8267   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8268   int ncell1=m1->getNumberOfCells();
8269   crI.push_back(0);
8270   for(int i=0;i<ncell1;i++)
8271     {
8272       std::vector<int> candidates2;
8273       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8274       std::map<INTERP_KERNEL::Node *,int> mapp;
8275       std::map<int,INTERP_KERNEL::Node *> mappRev;
8276       INTERP_KERNEL::QuadraticPolygon pol1;
8277       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8278       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8279       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8280       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8281                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8282       //
8283       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
8284       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8285       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8286       for(it1.first();!it1.finished();it1.next())
8287         edges1.insert(it1.current()->getPtr());
8288       //
8289       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8290       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8291       int ii=0;
8292       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8293         {
8294           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8295           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8296           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8297           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8298                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8299         }
8300       ii=0;
8301       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8302         {
8303           pol1.initLocationsWithOther(pol2s[ii]);
8304           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8305           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8306           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8307         }
8308       if(!edges1.empty())
8309         {
8310           try
8311             {
8312               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8313             }
8314           catch(INTERP_KERNEL::Exception& e)
8315             {
8316               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();
8317               throw INTERP_KERNEL::Exception(oss.str().c_str());
8318             }
8319         }
8320       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8321         (*it).second->decrRef();
8322     }
8323 }
8324
8325 /*!
8326  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8327  * 
8328  */
8329 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8330                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8331                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8332                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8333                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8334 {
8335   static const int SPACEDIM=2;
8336   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8337   desc2=DataArrayInt::New();
8338   descIndx2=DataArrayInt::New();
8339   revDesc2=DataArrayInt::New();
8340   revDescIndx2=DataArrayInt::New();
8341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8343   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8344   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8346   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8347   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8348   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8349   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8350   int ncell1=m1Desc->getNumberOfCells();
8351   int ncell2=m2Desc->getNumberOfCells();
8352   intersectEdge1.resize(ncell1);
8353   colinear2.resize(ncell2);
8354   subDiv2.resize(ncell2);
8355   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8356   std::vector<int> candidates1(1);
8357   int offset1=m1->getNumberOfNodes();
8358   int offset2=offset1+m2->getNumberOfNodes();
8359   for(int i=0;i<ncell1;i++)
8360     {
8361       std::vector<int> candidates2;
8362       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8363       if(!candidates2.empty())
8364         {
8365           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8366           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8367           candidates1[0]=i;
8368           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8369           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8370           delete pol2;
8371           delete pol1;
8372         }
8373       else
8374         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8375     }
8376   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8377   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8378 }
8379
8380 /*!
8381  * This method performs the 2nd step of Partition of 2D mesh.
8382  * This method has 4 inputs :
8383  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8384  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8385  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8386  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8387  * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8388  * \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.
8389  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8390  */
8391 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8392 {
8393   int offset1=m1->getNumberOfNodes();
8394   int ncell=m2->getNumberOfCells();
8395   const int *c=m2->getNodalConnectivity()->getConstPointer();
8396   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8397   const double *coo=m2->getCoords()->getConstPointer();
8398   const double *cooBis=m1->getCoords()->getConstPointer();
8399   int offset2=offset1+m2->getNumberOfNodes();
8400   intersectEdge.resize(ncell);
8401   for(int i=0;i<ncell;i++,cI++)
8402     {
8403       const std::vector<int>& divs=subDiv[i];
8404       int nnode=cI[1]-cI[0]-1;
8405       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8406       std::map<INTERP_KERNEL::Node *, int> mapp22;
8407       for(int j=0;j<nnode;j++)
8408         {
8409           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8410           int nnid=c[(*cI)+j+1];
8411           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8412           mapp22[nn]=nnid+offset1;
8413         }
8414       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8415       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8416         ((*it).second.first)->decrRef();
8417       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8418       std::map<INTERP_KERNEL::Node *,int> mapp3;
8419       for(std::size_t j=0;j<divs.size();j++)
8420         {
8421           int id=divs[j];
8422           INTERP_KERNEL::Node *tmp=0;
8423           if(id<offset1)
8424             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8425           else if(id<offset2)
8426             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8427           else
8428             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8429           addNodes[j]=tmp;
8430           mapp3[tmp]=id;
8431         }
8432       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8433       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8434         (*it)->decrRef();
8435       e->decrRef();
8436     }
8437 }
8438
8439 /*!
8440  * 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).
8441  * 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
8442  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8443  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8444  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8445  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8446  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8447  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8448  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8449  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8450  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8451  * \param [out] cut3DSuf input/output param.
8452  */
8453 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8454                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8455                                                    const int *desc, const int *descIndx, 
8456                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8457 {
8458   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8459   int nbOf3DSurfCell=(int)cut3DSurf.size();
8460   for(int i=0;i<nbOf3DSurfCell;i++)
8461     {
8462       std::vector<int> res;
8463       int offset=descIndx[i];
8464       int nbOfSeg=descIndx[i+1]-offset;
8465       for(int j=0;j<nbOfSeg;j++)
8466         {
8467           int edgeId=desc[offset+j];
8468           int status=cut3DCurve[edgeId];
8469           if(status!=-2)
8470             {
8471               if(status>-1)
8472                 res.push_back(status);
8473               else
8474                 {
8475                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8476                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8477                 }
8478             }
8479         }
8480       switch(res.size())
8481         {
8482         case 2:
8483           {
8484             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8485             break;
8486           }
8487         case 1:
8488         case 0:
8489           {
8490             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8491             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8492             if(res.size()==2)
8493               {
8494                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8495               }
8496             else
8497               {
8498                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8499               }
8500             break;
8501           }
8502         default:
8503           {// case when plane is on a multi colinear edge of a polyhedron
8504             if((int)res.size()==2*nbOfSeg)
8505               {
8506                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8507               }
8508             else
8509               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8510           }
8511         }
8512     }
8513 }
8514
8515 /*!
8516  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8517  * 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).
8518  * 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
8519  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8520  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8521  * \param desc is the descending connectivity 3D->3DSurf
8522  * \param descIndx is the descending connectivity index 3D->3DSurf
8523  */
8524 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8525                                                   const int *desc, const int *descIndx,
8526                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8527 {
8528   checkFullyDefined();
8529   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8531   const int *nodal3D=_nodal_connec->getConstPointer();
8532   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8533   int nbOfCells=getNumberOfCells();
8534   for(int i=0;i<nbOfCells;i++)
8535     {
8536       std::map<int, std::set<int> > m;
8537       int offset=descIndx[i];
8538       int nbOfFaces=descIndx[i+1]-offset;
8539       int start=-1;
8540       int end=-1;
8541       for(int j=0;j<nbOfFaces;j++)
8542         {
8543           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8544           if(p.first!=-1 && p.second!=-1)
8545             {
8546               if(p.first!=-2)
8547                 {
8548                   start=p.first; end=p.second;
8549                   m[p.first].insert(p.second);
8550                   m[p.second].insert(p.first);
8551                 }
8552               else
8553                 {
8554                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8555                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8556                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8557                   INTERP_KERNEL::NormalizedCellType cmsId;
8558                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8559                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8560                   for(unsigned k=0;k<nbOfNodesSon;k++)
8561                     {
8562                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8563                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8564                     }
8565                 }
8566             }
8567         }
8568       if(m.empty())
8569         continue;
8570       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8571       int prev=end;
8572       while(end!=start)
8573         {
8574           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8575           const std::set<int>& s=(*it).second;
8576           std::set<int> s2; s2.insert(prev);
8577           std::set<int> s3;
8578           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8579           if(s3.size()==1)
8580             {
8581               int val=*s3.begin();
8582               conn.push_back(start);
8583               prev=start;
8584               start=val;
8585             }
8586           else
8587             start=end;
8588         }
8589       conn.push_back(end);
8590       if(conn.size()>3)
8591         {
8592           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8593           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8594           cellIds->pushBackSilent(i);
8595         }
8596     }
8597 }
8598
8599 /*!
8600  * 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
8601  * 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
8602  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8603  * 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
8604  * 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.
8605  * 
8606  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8607  */
8608 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8609 {
8610   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8611   if(sz>=4)
8612     {
8613       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8614       if(cm.getDimension()==2)
8615         {
8616           const int *node=nodalConnBg+1;
8617           int startNode=*node++;
8618           double refX=coords[2*startNode];
8619           for(;node!=nodalConnEnd;node++)
8620             {
8621               if(coords[2*(*node)]<refX)
8622                 {
8623                   startNode=*node;
8624                   refX=coords[2*startNode];
8625                 }
8626             }
8627           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8628           refX=1e300;
8629           double tmp1;
8630           double tmp2[2];
8631           double angle0=-M_PI/2;
8632           //
8633           int nextNode=-1;
8634           int prevNode=-1;
8635           double resRef;
8636           double angleNext=0.;
8637           while(nextNode!=startNode)
8638             {
8639               nextNode=-1;
8640               resRef=1e300;
8641               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8642                 {
8643                   if(*node!=tmpOut.back() && *node!=prevNode)
8644                     {
8645                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8646                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8647                       double res;
8648                       if(angleM<=angle0)
8649                         res=angle0-angleM;
8650                       else
8651                         res=angle0-angleM+2.*M_PI;
8652                       if(res<resRef)
8653                         {
8654                           nextNode=*node;
8655                           resRef=res;
8656                           angleNext=angleM;
8657                         }
8658                     }
8659                 }
8660               if(nextNode!=startNode)
8661                 {
8662                   angle0=angleNext-M_PI;
8663                   if(angle0<-M_PI)
8664                     angle0+=2*M_PI;
8665                   prevNode=tmpOut.back();
8666                   tmpOut.push_back(nextNode);
8667                 }
8668             }
8669           std::vector<int> tmp3(2*(sz-1));
8670           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8671           std::copy(nodalConnBg+1,nodalConnEnd,it);
8672           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8673             {
8674               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8675               return false;
8676             }
8677           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8678             {
8679               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8680               return false;
8681             }
8682           else
8683             {
8684               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8685               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8686               return true;
8687             }
8688         }
8689       else
8690         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8691     }
8692   else
8693     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8694 }
8695
8696 /*!
8697  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8698  * 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.
8699  * 
8700  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8701  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8702  * \param [in,out] arr array in which the remove operation will be done.
8703  * \param [in,out] arrIndx array in the remove operation will modify
8704  * \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])
8705  * \return true if \b arr and \b arrIndx have been modified, false if not.
8706  */
8707 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8708 {
8709   if(!arrIndx || !arr)
8710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8711   if(offsetForRemoval<0)
8712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8713   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8714   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8715   int *arrIPtr=arrIndx->getPointer();
8716   *arrIPtr++=0;
8717   int previousArrI=0;
8718   const int *arrPtr=arr->getConstPointer();
8719   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8720   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8721     {
8722       if(*arrIPtr-previousArrI>offsetForRemoval)
8723         {
8724           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8725             {
8726               if(s.find(*work)==s.end())
8727                 arrOut.push_back(*work);
8728             }
8729         }
8730       previousArrI=*arrIPtr;
8731       *arrIPtr=(int)arrOut.size();
8732     }
8733   if(arr->getNumberOfTuples()==(int)arrOut.size())
8734     return false;
8735   arr->alloc((int)arrOut.size(),1);
8736   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8737   return true;
8738 }
8739
8740 /*!
8741  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8742  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8743  * The selection of extraction is done standardly in new2old format.
8744  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8745  *
8746  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8747  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8748  * \param [in] arrIn arr origin array from which the extraction will be done.
8749  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8750  * \param [out] arrOut the resulting array
8751  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8752  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8753  */
8754 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8755                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8756 {
8757   if(!arrIn || !arrIndxIn)
8758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8759   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8760   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8762   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8763   const int *arrInPtr=arrIn->getConstPointer();
8764   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8765   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8766   if(nbOfGrps<0)
8767     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8768   int maxSizeOfArr=arrIn->getNumberOfTuples();
8769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8771   arrIo->alloc((int)(sz+1),1);
8772   const int *idsIt=idsOfSelectBg;
8773   int *work=arrIo->getPointer();
8774   *work++=0;
8775   int lgth=0;
8776   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8777     {
8778       if(*idsIt>=0 && *idsIt<nbOfGrps)
8779         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8780       else
8781         {
8782           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8783           throw INTERP_KERNEL::Exception(oss.str().c_str());
8784         }
8785       if(lgth>=work[-1])
8786         *work=lgth;
8787       else
8788         {
8789           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8790           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8791           throw INTERP_KERNEL::Exception(oss.str().c_str());
8792         }
8793     }
8794   arro->alloc(lgth,1);
8795   work=arro->getPointer();
8796   idsIt=idsOfSelectBg;
8797   for(std::size_t i=0;i<sz;i++,idsIt++)
8798     {
8799       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8800         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8801       else
8802         {
8803           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8804           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8805           throw INTERP_KERNEL::Exception(oss.str().c_str());
8806         }
8807     }
8808   arrOut=arro.retn();
8809   arrIndexOut=arrIo.retn();
8810 }
8811
8812 /*!
8813  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8814  * 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 ).
8815  * The selection of extraction is done standardly in new2old format.
8816  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8817  *
8818  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8819  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8820  * \param [in] arrIn arr origin array from which the extraction will be done.
8821  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8822  * \param [out] arrOut the resulting array
8823  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8824  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8825  */
8826 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8827                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8828 {
8829   if(!arrIn || !arrIndxIn)
8830     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8831   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8832   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8833     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8834   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8835   const int *arrInPtr=arrIn->getConstPointer();
8836   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8837   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8838   if(nbOfGrps<0)
8839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8840   int maxSizeOfArr=arrIn->getNumberOfTuples();
8841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8843   arrIo->alloc((int)(sz+1),1);
8844   int idsIt=idsOfSelectStart;
8845   int *work=arrIo->getPointer();
8846   *work++=0;
8847   int lgth=0;
8848   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8849     {
8850       if(idsIt>=0 && idsIt<nbOfGrps)
8851         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8852       else
8853         {
8854           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8855           throw INTERP_KERNEL::Exception(oss.str().c_str());
8856         }
8857       if(lgth>=work[-1])
8858         *work=lgth;
8859       else
8860         {
8861           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8862           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8863           throw INTERP_KERNEL::Exception(oss.str().c_str());
8864         }
8865     }
8866   arro->alloc(lgth,1);
8867   work=arro->getPointer();
8868   idsIt=idsOfSelectStart;
8869   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8870     {
8871       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8872         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8873       else
8874         {
8875           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8876           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8877           throw INTERP_KERNEL::Exception(oss.str().c_str());
8878         }
8879     }
8880   arrOut=arro.retn();
8881   arrIndexOut=arrIo.retn();
8882 }
8883
8884 /*!
8885  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8886  * 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
8887  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8888  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8889  *
8890  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8891  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8892  * \param [in] arrIn arr origin array from which the extraction will be done.
8893  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8894  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8895  * \param [in] srcArrIndex index array of \b srcArr
8896  * \param [out] arrOut the resulting array
8897  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8898  * 
8899  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8900  */
8901 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8902                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8903                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8904 {
8905   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8906     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8909   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8910   std::vector<bool> v(nbOfTuples,true);
8911   int offset=0;
8912   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8913   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8914   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8915     {
8916       if(*it>=0 && *it<nbOfTuples)
8917         {
8918           v[*it]=false;
8919           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8920         }
8921       else
8922         {
8923           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8924           throw INTERP_KERNEL::Exception(oss.str().c_str());
8925         }
8926     }
8927   srcArrIndexPtr=srcArrIndex->getConstPointer();
8928   arrIo->alloc(nbOfTuples+1,1);
8929   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8930   const int *arrInPtr=arrIn->getConstPointer();
8931   const int *srcArrPtr=srcArr->getConstPointer();
8932   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8933   int *arroPtr=arro->getPointer();
8934   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8935     {
8936       if(v[ii])
8937         {
8938           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8939           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8940         }
8941       else
8942         {
8943           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8944           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8945           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8946         }
8947     }
8948   arrOut=arro.retn();
8949   arrIndexOut=arrIo.retn();
8950 }
8951
8952 /*!
8953  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8954  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8955  *
8956  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8957  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8958  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8959  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8960  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8961  * \param [in] srcArrIndex index array of \b srcArr
8962  * 
8963  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8964  */
8965 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8966                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8967 {
8968   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8970   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8971   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8972   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8973   int *arrInOutPtr=arrInOut->getPointer();
8974   const int *srcArrPtr=srcArr->getConstPointer();
8975   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8976     {
8977       if(*it>=0 && *it<nbOfTuples)
8978         {
8979           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8980             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8981           else
8982             {
8983               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] !";
8984               throw INTERP_KERNEL::Exception(oss.str().c_str());
8985             }
8986         }
8987       else
8988         {
8989           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8990           throw INTERP_KERNEL::Exception(oss.str().c_str());
8991         }
8992     }
8993 }
8994
8995 /*!
8996  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8997  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8998  * 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]].
8999  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9000  * A negative value in \b arrIn means that it is ignored.
9001  * 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.
9002  * 
9003  * \param [in] arrIn arr origin array from which the extraction will be done.
9004  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9005  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9006  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9007  */
9008 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9009 {
9010   int seed=0,nbOfDepthPeelingPerformed=0;
9011   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9012 }
9013
9014 /*!
9015  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9016  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9017  * 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]].
9018  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9019  * A negative value in \b arrIn means that it is ignored.
9020  * 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.
9021  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9022  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9023  * \param [in] arrIn arr origin array from which the extraction will be done.
9024  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9025  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9026  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9027  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9028  * \sa MEDCouplingUMesh::partitionBySpreadZone
9029  */
9030 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9031 {
9032   nbOfDepthPeelingPerformed=0;
9033   if(!arrIndxIn)
9034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9035   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9036   if(nbOfTuples<=0)
9037     {
9038       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9039       return ret;
9040     }
9041   //
9042   std::vector<bool> fetched(nbOfTuples,false);
9043   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9044 }
9045
9046 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9047 {
9048   nbOfDepthPeelingPerformed=0;
9049   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9051   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9052   std::vector<bool> fetched2(nbOfTuples,false);
9053   int i=0;
9054   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9055     {
9056       if(*seedElt>=0 && *seedElt<nbOfTuples)
9057         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9058       else
9059         { 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()); }
9060     }
9061   const int *arrInPtr=arrIn->getConstPointer();
9062   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9063   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9064   std::vector<int> idsToFetch1(seedBg,seedEnd);
9065   std::vector<int> idsToFetch2;
9066   std::vector<int> *idsToFetch=&idsToFetch1;
9067   std::vector<int> *idsToFetchOther=&idsToFetch2;
9068   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9069     {
9070       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9071         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9072           if(!fetched[*it2])
9073             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9074       std::swap(idsToFetch,idsToFetchOther);
9075       idsToFetchOther->clear();
9076       nbOfDepthPeelingPerformed++;
9077     }
9078   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9079   i=0;
9080   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9081   int *retPtr=ret->getPointer();
9082   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9083     if(*it)
9084       *retPtr++=i;
9085   return ret.retn();
9086 }
9087
9088 /*!
9089  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9090  * 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
9091  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9092  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9093  *
9094  * \param [in] start begin of set of ids of the input extraction (included)
9095  * \param [in] end end of set of ids of the input extraction (excluded)
9096  * \param [in] step step of the set of ids in range mode.
9097  * \param [in] arrIn arr origin array from which the extraction will be done.
9098  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9099  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9100  * \param [in] srcArrIndex index array of \b srcArr
9101  * \param [out] arrOut the resulting array
9102  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9103  * 
9104  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9105  */
9106 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9107                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9108                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9109 {
9110   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9112   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9114   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9115   int offset=0;
9116   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9117   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9118   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9119   int it=start;
9120   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9121     {
9122       if(it>=0 && it<nbOfTuples)
9123         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9124       else
9125         {
9126           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9127           throw INTERP_KERNEL::Exception(oss.str().c_str());
9128         }
9129     }
9130   srcArrIndexPtr=srcArrIndex->getConstPointer();
9131   arrIo->alloc(nbOfTuples+1,1);
9132   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9133   const int *arrInPtr=arrIn->getConstPointer();
9134   const int *srcArrPtr=srcArr->getConstPointer();
9135   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9136   int *arroPtr=arro->getPointer();
9137   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9138     {
9139       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9140       if(pos<0)
9141         {
9142           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9143           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9144         }
9145       else
9146         {
9147           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9148           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9149         }
9150     }
9151   arrOut=arro.retn();
9152   arrIndexOut=arrIo.retn();
9153 }
9154
9155 /*!
9156  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9157  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9158  *
9159  * \param [in] start begin of set of ids of the input extraction (included)
9160  * \param [in] end end of set of ids of the input extraction (excluded)
9161  * \param [in] step step of the set of ids in range mode.
9162  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9163  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9164  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9165  * \param [in] srcArrIndex index array of \b srcArr
9166  * 
9167  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9168  */
9169 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9170                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9171 {
9172   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9174   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9175   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9176   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9177   int *arrInOutPtr=arrInOut->getPointer();
9178   const int *srcArrPtr=srcArr->getConstPointer();
9179   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9180   int it=start;
9181   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9182     {
9183       if(it>=0 && it<nbOfTuples)
9184         {
9185           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9186             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9187           else
9188             {
9189               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9190               throw INTERP_KERNEL::Exception(oss.str().c_str());
9191             }
9192         }
9193       else
9194         {
9195           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9196           throw INTERP_KERNEL::Exception(oss.str().c_str());
9197         }
9198     }
9199 }
9200
9201 /*!
9202  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9203  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9204  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9205  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9206  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9207  * 
9208  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9209  */
9210 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9211 {
9212   checkFullyDefined();
9213   int mdim=getMeshDimension();
9214   int spaceDim=getSpaceDimension();
9215   if(mdim!=spaceDim)
9216     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9217   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9218   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9219   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9220   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9221   ret->setCoords(getCoords());
9222   ret->allocateCells((int)partition.size());
9223   //
9224   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9225     {
9226       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9227       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9228       switch(mdim)
9229         {
9230         case 2:
9231           cell=tmp->buildUnionOf2DMesh();
9232           break;
9233         case 3:
9234           cell=tmp->buildUnionOf3DMesh();
9235           break;
9236         default:
9237           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9238         }
9239       
9240       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9241     }
9242   //
9243   ret->finishInsertingCells();
9244   return ret.retn();
9245 }
9246
9247 /*!
9248  * This method partitions \b this into contiguous zone.
9249  * This method only needs a well defined connectivity. Coordinates are not considered here.
9250  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9251  */
9252 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9253 {
9254   int nbOfCellsCur=getNumberOfCells();
9255   std::vector<DataArrayInt *> ret;
9256   if(nbOfCellsCur<=0)
9257     return ret;
9258   DataArrayInt *neigh=0,*neighI=0;
9259   computeNeighborsOfCells(neigh,neighI);
9260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9261   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9262   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9263   int seed=0;
9264   while(seed<nbOfCellsCur)
9265     {
9266       int nbOfPeelPerformed=0;
9267       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9268       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9269     }
9270   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9271     ret.push_back((*it).retn());
9272   return ret;
9273 }
9274
9275 /*!
9276  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9277  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9278  *
9279  * \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.
9280  * \return a newly allocated DataArrayInt to be managed by the caller.
9281  * \throw In case of \a code has not the right format (typically of size 3*n)
9282  */
9283 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9284 {
9285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9286   std::size_t nb=code.size()/3;
9287   if(code.size()%3!=0)
9288     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9289   ret->alloc((int)nb,2);
9290   int *retPtr=ret->getPointer();
9291   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9292     {
9293       retPtr[0]=code[3*i+2];
9294       retPtr[1]=code[3*i+2]+code[3*i+1];
9295     }
9296   return ret.retn();
9297 }
9298
9299 /*!
9300  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9301  * All cells in \a this are expected to be linear 3D cells.
9302  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9303  * It leads to an increase to number of cells.
9304  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9305  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9306  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9307  *
9308  * \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.
9309  *                      For all other cells, the splitting policy will be ignored.
9310  * \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. 
9311  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9312  *          an id of old cell producing it. The caller is to delete this array using
9313  *         decrRef() as it is no more needed.
9314  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9315  * 
9316  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9317  * \throw If \a this is not fully constituted with linear 3D cells.
9318  * \sa MEDCouplingUMesh::simplexize
9319  */
9320 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9321 {
9322   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9323   checkConnectivityFullyDefined();
9324   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9326   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9327   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9329   int *retPt(ret->getPointer());
9330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9331   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9332   const int *oldc(_nodal_connec->begin());
9333   const int *oldci(_nodal_connec_index->begin());
9334   const double *coords(_coords->begin());
9335   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9336     {
9337       std::vector<int> a; std::vector<double> b;
9338       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9339       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9340       const int *aa(&a[0]);
9341       if(!b.empty())
9342         {
9343           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9344             if(*it<0)
9345               *it=(-(*(it))-1+nbNodes);
9346           addPts->insertAtTheEnd(b.begin(),b.end());
9347           nbNodes+=(int)b.size()/3;
9348         }
9349       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9350         newConn->insertAtTheEnd(aa,aa+4);
9351     }
9352   if(!addPts->empty())
9353     {
9354       addPts->rearrange(3);
9355       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9356       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9357       ret0->setCoords(addPts);
9358     }
9359   else
9360     {
9361       nbOfAdditionalPoints=0;
9362       ret0->setCoords(getCoords());
9363     }
9364   ret0->setNodalConnectivity(newConn);
9365   //
9366   ret->computeOffsets2();
9367   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9368   return ret0.retn();
9369 }
9370
9371 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9372                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9373 {
9374   if(mesh)
9375     {
9376       mesh->incrRef();
9377       _nb_cell=mesh->getNumberOfCells();
9378     }
9379 }
9380
9381 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9382 {
9383   if(_mesh)
9384     _mesh->decrRef();
9385   if(_own_cell)
9386     delete _cell;
9387 }
9388
9389 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9390                                                                                                                                _own_cell(false),_cell_id(bg-1),
9391                                                                                                                                _nb_cell(end)
9392 {
9393   if(mesh)
9394     mesh->incrRef();
9395 }
9396
9397 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9398 {
9399   _cell_id++;
9400   if(_cell_id<_nb_cell)
9401     {
9402       _cell->next();
9403       return _cell;
9404     }
9405   else
9406     return 0;
9407 }
9408
9409 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9410 {
9411   if(_mesh)
9412     _mesh->incrRef();
9413 }
9414
9415 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9416 {
9417   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9418 }
9419
9420 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9421 {
9422   if(_mesh)
9423     _mesh->decrRef();
9424 }
9425
9426 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9427                                                                                                                                                                   _itc(itc),
9428                                                                                                                                                                   _bg(bg),_end(end)
9429 {
9430   if(_mesh)
9431     _mesh->incrRef();
9432 }
9433
9434 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9435 {
9436   if(_mesh)
9437     _mesh->decrRef();
9438 }
9439
9440 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9441 {
9442   return _type;
9443 }
9444
9445 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9446 {
9447   return _end-_bg;
9448 }
9449
9450 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9451 {
9452   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9453 }
9454
9455 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9456 {
9457   if(mesh)
9458     {
9459       mesh->incrRef();
9460       _nb_cell=mesh->getNumberOfCells();
9461     }
9462 }
9463
9464 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9465 {
9466   if(_mesh)
9467     _mesh->decrRef();
9468   delete _cell;
9469 }
9470
9471 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9472 {
9473   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9474   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9475   if(_cell_id<_nb_cell)
9476     {
9477       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9478       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9479       int startId=_cell_id;
9480       _cell_id+=nbOfElems;
9481       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9482     }
9483   else
9484     return 0;
9485 }
9486
9487 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9488 {
9489   if(mesh)
9490     {
9491       _conn=mesh->getNodalConnectivity()->getPointer();
9492       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9493     }
9494 }
9495
9496 void MEDCouplingUMeshCell::next()
9497 {
9498   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9499     {
9500       _conn+=_conn_lgth;
9501       _conn_indx++;
9502     }
9503   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9504 }
9505
9506 std::string MEDCouplingUMeshCell::repr() const
9507 {
9508   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9509     {
9510       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9511       oss << " : ";
9512       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9513       return oss.str();
9514     }
9515   else
9516     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9517 }
9518
9519 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9520 {
9521   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9522     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9523   else
9524     return INTERP_KERNEL::NORM_ERROR;
9525 }
9526
9527 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9528 {
9529   lgth=_conn_lgth;
9530   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9531     return _conn;
9532   else
9533     return 0;
9534 }