Salome HOME
2cf2890fd07006c323d36537a72eb55de65244cd
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2016  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, or (at your option) any later version.
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 (EDF R&D)
20
21 #include "MEDCouplingUMesh.txx"
22 #include "MEDCouplingCMesh.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44 #include "OrientationInverter.hxx"
45 #include "MEDCouplingUMesh_internal.hxx"
46
47 #include <sstream>
48 #include <fstream>
49 #include <numeric>
50 #include <cstring>
51 #include <limits>
52 #include <list>
53
54 using namespace MEDCoupling;
55
56 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
57
58 /// @cond INTERNAL
59 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_PENTA18, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
60 const int MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[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,32,-1,25,42,36,4};
61 /// @endcond
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New()
64 {
65   return new MEDCouplingUMesh;
66 }
67
68 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
69 {
70   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
71   ret->setName(meshName);
72   ret->setMeshDimension(meshDim);
73   return ret;
74 }
75
76 /*!
77  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
78  * between \a this and the new mesh.
79  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
80  *          delete this mesh using decrRef() as it is no more needed. 
81  */
82 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
83 {
84   return clone(true);
85 }
86
87
88 /*!
89  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
90  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
91  * this mesh are shared by the new mesh.
92  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
93  *          delete this mesh using decrRef() as it is no more needed. 
94  */
95 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
96 {
97   return new MEDCouplingUMesh(*this,recDeepCpy);
98 }
99
100 /*!
101  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
102  * The coordinates are shared between \a this and the returned instance.
103  * 
104  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
105  * \sa MEDCouplingUMesh::deepCopy
106  */
107 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
108 {
109   checkConnectivityFullyDefined();
110   MCAuto<MEDCouplingUMesh> ret=clone(false);
111   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
112   ret->setConnectivity(c,ci);
113   return ret.retn();
114 }
115
116 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
117 {
118   if(!other)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
120   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
121   if(!otherC)
122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
123   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
124   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
125 }
126
127 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
128 {
129   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
130   return ret;
131 }
132
133 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
134 {
135   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
136   ret.push_back(_nodal_connec);
137   ret.push_back(_nodal_connec_index);
138   return ret;
139 }
140
141 void MEDCouplingUMesh::updateTime() const
142 {
143   MEDCouplingPointSet::updateTime();
144   if(_nodal_connec)
145     {
146       updateTimeWith(*_nodal_connec);
147     }
148   if(_nodal_connec_index)
149     {
150       updateTimeWith(*_nodal_connec_index);
151     }
152 }
153
154 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
155 {
156 }
157
158 /*!
159  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
160  * then \a this mesh is most probably is writable, exchangeable and available for most
161  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
162  * this method to check that all is in order with \a this mesh.
163  *  \throw If the mesh dimension is not set.
164  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
165  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
166  *  \throw If the connectivity data array has more than one component.
167  *  \throw If the connectivity data array has a named component.
168  *  \throw If the connectivity index data array has more than one component.
169  *  \throw If the connectivity index data array has a named component.
170  */
171 void MEDCouplingUMesh::checkConsistencyLight() const
172 {
173   if(_mesh_dim<-1)
174     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
175   if(_mesh_dim!=-1)
176     MEDCouplingPointSet::checkConsistencyLight();
177   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
178     {
179       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
180         {
181           std::ostringstream message;
182           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
183           throw INTERP_KERNEL::Exception(message.str().c_str());
184         }
185     }
186   if(_nodal_connec)
187     {
188       if(_nodal_connec->getNumberOfComponents()!=1)
189         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
190       if(_nodal_connec->getInfoOnComponent(0)!="")
191         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
192     }
193   else
194     if(_mesh_dim!=-1)
195       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
196   if(_nodal_connec_index)
197     {
198       if(_nodal_connec_index->getNumberOfComponents()!=1)
199         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
200       if(_nodal_connec_index->getInfoOnComponent(0)!="")
201         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
202     }
203   else
204     if(_mesh_dim!=-1)
205       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
206 }
207
208 /*!
209  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
210  * then \a this mesh is most probably is writable, exchangeable and available for all
211  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
212  * method thoroughly checks the nodal connectivity.
213  *  \param [in] eps - a not used parameter.
214  *  \throw If the mesh dimension is not set.
215  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
216  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
217  *  \throw If the connectivity data array has more than one component.
218  *  \throw If the connectivity data array has a named component.
219  *  \throw If the connectivity index data array has more than one component.
220  *  \throw If the connectivity index data array has a named component.
221  *  \throw If number of nodes defining an element does not correspond to the type of element.
222  *  \throw If the nodal connectivity includes an invalid node id.
223  */
224 void MEDCouplingUMesh::checkConsistency(double eps) const
225 {
226   checkConsistencyLight();
227   if(_mesh_dim==-1)
228     return ;
229   int meshDim=getMeshDimension();
230   int nbOfNodes=getNumberOfNodes();
231   int nbOfCells=getNumberOfCells();
232   const int *ptr=_nodal_connec->getConstPointer();
233   const int *ptrI=_nodal_connec_index->getConstPointer();
234   for(int i=0;i<nbOfCells;i++)
235     {
236       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
237       if((int)cm.getDimension()!=meshDim)
238         {
239           std::ostringstream oss;
240           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
241           throw INTERP_KERNEL::Exception(oss.str());
242         }
243       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
244       if(!cm.isDynamic())
245         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
246           {
247             std::ostringstream oss;
248             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
249             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
250             throw INTERP_KERNEL::Exception(oss.str());
251           }
252       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
253         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
254           {
255             std::ostringstream oss;
256             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
257             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
258             throw INTERP_KERNEL::Exception(oss.str());
259           }
260       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
261         {
262           int nodeId=*w;
263           if(nodeId>=0)
264             {
265               if(nodeId>=nbOfNodes)
266                 {
267                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
268                   throw INTERP_KERNEL::Exception(oss.str());
269                 }
270             }
271           else if(nodeId<-1)
272             {
273               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
274               throw INTERP_KERNEL::Exception(oss.str());
275             }
276           else
277             {
278               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
279                 {
280                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
281                   throw INTERP_KERNEL::Exception(oss.str());
282                 }
283             }
284         }
285     }
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. 
305  * The closer the estimation to the number of cells effectively inserted, the less need the library requires
306  * to reallocate memory. If the number of cells to be inserted is not known simply assign 0 to this parameter.
307  * If a nodal connectivity previously existed before the call of this method, it will be reset.
308  *
309  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
310  *
311  *  \if ENABLE_EXAMPLES
312  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
313  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
314  *  \endif
315  */
316 void MEDCouplingUMesh::allocateCells(int nbOfCells)
317 {
318   if(nbOfCells<0)
319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
320   if(_nodal_connec_index)
321     {
322       _nodal_connec_index->decrRef();
323     }
324   if(_nodal_connec)
325     {
326       _nodal_connec->decrRef();
327     }
328   _nodal_connec_index=DataArrayInt::New();
329   _nodal_connec_index->reserve(nbOfCells+1);
330   _nodal_connec_index->pushBackSilent(0);
331   _nodal_connec=DataArrayInt::New();
332   _nodal_connec->reserve(2*nbOfCells);
333   _types.clear();
334   declareAsNew();
335 }
336
337 /*!
338  * Appends a cell to the connectivity array. For deeper understanding what is
339  * happening see \ref MEDCouplingUMeshNodalConnectivity.
340  *  \param [in] type - type of cell to add.
341  *  \param [in] size - number of nodes constituting this cell.
342  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
343  * 
344  *  \if ENABLE_EXAMPLES
345  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
346  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
347  *  \endif
348  */
349 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
350 {
351   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
352   if(_nodal_connec_index==0)
353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
354   if((int)cm.getDimension()==_mesh_dim)
355     {
356       if(!cm.isDynamic())
357         if(size!=(int)cm.getNumberOfNodes())
358           {
359             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
360             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
361             throw INTERP_KERNEL::Exception(oss.str());
362           }
363       int idx=_nodal_connec_index->back();
364       int val=idx+size+1;
365       _nodal_connec_index->pushBackSilent(val);
366       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
367       _types.insert(type);
368     }
369   else
370     {
371       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
372       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
373       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
374       throw INTERP_KERNEL::Exception(oss.str());
375     }
376 }
377
378 /*!
379  * Compacts data arrays to release unused memory. This method is to be called after
380  * finishing cell insertion using \a this->insertNextCell().
381  * 
382  *  \if ENABLE_EXAMPLES
383  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
384  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
385  *  \endif
386  */
387 void MEDCouplingUMesh::finishInsertingCells()
388 {
389   _nodal_connec->pack();
390   _nodal_connec_index->pack();
391   _nodal_connec->declareAsNew();
392   _nodal_connec_index->declareAsNew();
393   updateTime();
394 }
395
396 /*!
397  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
398  * Useful for python users.
399  */
400 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
401 {
402   return new MEDCouplingUMeshCellIterator(this);
403 }
404
405 /*!
406  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
407  * If \a this is not so that the cells are grouped by geo types, this method will throw an exception.
408  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
409  * Useful for python users.
410  */
411 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
412 {
413   if(!checkConsecutiveCellTypes())
414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
415   return new MEDCouplingUMeshCellByTypeEntry(this);
416 }
417
418 /*!
419  * Returns a set of all cell types available in \a this mesh.
420  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
421  * \warning this method does not throw any exception even if \a this is not defined.
422  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
423  */
424 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
425 {
426   return _types;
427 }
428
429 /*!
430  * This method returns the sorted list of geometric types in \a this.
431  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
432  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
433  *
434  * \throw if connectivity in \a this is not correctly defined.
435  *  
436  * \sa MEDCouplingMesh::getAllGeoTypes
437  */
438 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
439 {
440   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
441   checkConnectivityFullyDefined();
442   int nbOfCells(getNumberOfCells());
443   if(nbOfCells==0)
444     return ret;
445   if(getNodalConnectivityArrayLen()<1)
446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
447   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
448   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
449   for(int i=1;i<nbOfCells;i++,ci++)
450     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
451       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
452   return ret;
453 }
454
455 /*!
456  * This method is a method that compares \a this and \a other.
457  * This method compares \b all attributes, even names and component names.
458  */
459 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
460 {
461   if(!other)
462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
463   std::ostringstream oss; oss.precision(15);
464   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
465   if(!otherC)
466     {
467       reason="mesh given in input is not castable in MEDCouplingUMesh !";
468       return false;
469     }
470   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
471     return false;
472   if(_mesh_dim!=otherC->_mesh_dim)
473     {
474       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
475       reason=oss.str();
476       return false;
477     }
478   if(_types!=otherC->_types)
479     {
480       oss << "umesh geometric type mismatch :\nThis geometric types are :";
481       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
482         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
483       oss << "\nOther geometric types are :";
484       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
485         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
486       reason=oss.str();
487       return false;
488     }
489   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
490     if(_nodal_connec==0 || otherC->_nodal_connec==0)
491       {
492         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
493         return false;
494       }
495   if(_nodal_connec!=otherC->_nodal_connec)
496     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
497       {
498         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
499         return false;
500       }
501   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
502     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
503       {
504         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
505         return false;
506       }
507   if(_nodal_connec_index!=otherC->_nodal_connec_index)
508     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
509       {
510         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
511         return false;
512       }
513   return true;
514 }
515
516 /*!
517  * Checks if data arrays of this mesh (node coordinates, nodal
518  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
519  * not considered.
520  *  \param [in] other - the mesh to compare with.
521  *  \param [in] prec - precision value used to compare node coordinates.
522  *  \return bool - \a true if the two meshes are same.
523  */
524 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
525 {
526   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
527   if(!otherC)
528     return false;
529   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
530     return false;
531   if(_mesh_dim!=otherC->_mesh_dim)
532     return false;
533   if(_types!=otherC->_types)
534     return false;
535   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
536     if(_nodal_connec==0 || otherC->_nodal_connec==0)
537       return false;
538   if(_nodal_connec!=otherC->_nodal_connec)
539     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
540       return false;
541   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
542     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
543       return false;
544   if(_nodal_connec_index!=otherC->_nodal_connec_index)
545     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
546       return false;
547   return true;
548 }
549
550 /*!
551  * Checks if \a this and \a other meshes are geometrically equivalent with high
552  * probability, else an exception is thrown. The meshes are considered equivalent if
553  * (1) meshes contain the same number of nodes and the same number of elements of the
554  * same types (2) three cells of the two meshes (first, last and middle) are based
555  * on coincident nodes (with a specified precision).
556  *  \param [in] other - the mesh to compare with.
557  *  \param [in] prec - the precision used to compare nodes of the two meshes.
558  *  \throw If the two meshes do not match.
559  */
560 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
561 {
562   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
563   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
564   if(!otherC)
565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
566 }
567
568 /*!
569  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
570  * cells each node belongs to.
571  * \warning For speed reasons, this method does not check if node ids in the nodal
572  *          connectivity correspond to the size of node coordinates array.
573  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
574  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
575  *        dividing cell ids in \a revNodal into groups each referring to one
576  *        node. Its every element (except the last one) is an index pointing to the
577  *         first id of a group of cells. For example cells sharing the node #1 are 
578  *        described by following range of indices: 
579  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
580  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
581  *        Number of cells sharing the *i*-th node is
582  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
583  * \throw If the coordinates array is not set.
584  * \throw If the nodal connectivity of cells is not defined.
585  * 
586  * \if ENABLE_EXAMPLES
587  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
588  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
589  * \endif
590  */
591 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
592 {
593   checkFullyDefined();
594   int nbOfNodes(getNumberOfNodes());
595   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
596   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
597   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
598   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
599   int nbOfCells(getNumberOfCells()),nbOfEltsInRevNodal(0);
600   for(int eltId=0;eltId<nbOfCells;eltId++)
601     {
602       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
603       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
604         if(*iter>=0)//for polyhedrons
605           {
606             nbOfEltsInRevNodal++;
607             revNodalIndxPtr[(*iter)+1]++;
608           }
609     }
610   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
611   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
612   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
613   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
614   for(int eltId=0;eltId<nbOfCells;eltId++)
615     {
616       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
617       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
618       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
619         if(*iter>=0)//for polyhedrons
620           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
621     }
622 }
623
624 /*!
625  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
626  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
627  * describing correspondence between cells of \a this and the result meshes are
628  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
629  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
630  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
631  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
632  * \warning For speed reasons, this method does not check if node ids in the nodal
633  *          connectivity correspond to the size of node coordinates array.
634  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
635  *          to write this mesh to the MED file, its cells must be sorted using
636  *          sortCellsInMEDFileFrmt().
637  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
638  *         each cell of \a this mesh.
639  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
640  *        dividing cell ids in \a desc into groups each referring to one
641  *        cell of \a this mesh. Its every element (except the last one) is an index
642  *        pointing to the first id of a group of cells. For example cells of the
643  *        result mesh bounding the cell #1 of \a this mesh are described by following
644  *        range of indices:
645  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
646  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
647  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
648  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
649  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
650  *         by each cell of the result mesh.
651  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
652  *        in the result mesh,
653  *        dividing cell ids in \a revDesc into groups each referring to one
654  *        cell of the result mesh the same way as \a descIndx divides \a desc.
655  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
656  *        delete this mesh using decrRef() as it is no more needed.
657  *  \throw If the coordinates array is not set.
658  *  \throw If the nodal connectivity of cells is node defined.
659  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
660  *         revDescIndx == NULL.
661  * 
662  *  \if ENABLE_EXAMPLES
663  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
664  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
665  *  \endif
666  * \sa buildDescendingConnectivity2()
667  */
668 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
669 {
670   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
671 }
672
673 /*!
674  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
675  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
676  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
677  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
678  * \sa MEDCouplingUMesh::buildDescendingConnectivity
679  */
680 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
681 {
682   checkFullyDefined();
683   if(getMeshDimension()!=3)
684     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
685   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
686 }
687
688 /*!
689  * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
690  * This method works for both meshes with mesh dimension equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
691  * 
692  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
693  */
694 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
695 {
696    checkFullyDefined();
697    switch(getMeshDimension())
698      {
699      case 2:
700        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
701      case 3:
702        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
703      default:
704        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
705      }
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 (\ref numbering-indirect) 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 (\ref numbering-indirect) 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  *  \if ENABLE_EXAMPLES
754  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
755  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
756  *  \endif
757  * \sa buildDescendingConnectivity()
758  */
759 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
760 {
761   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
762 }
763
764 /*!
765  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
766  * For speed reasons no check of this will be done. This method calls
767  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
768  * This method lists cell by cell in \b this which are its neighbors. To compute the result
769  * only connectivities are considered.
770  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
771  * The format of return is hence \ref numbering-indirect.
772  *
773  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
774  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
775  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
776  * is equal to the last values in \b neighborsIndx.
777  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
778  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
779  */
780 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
781 {
782   MCAuto<DataArrayInt> desc=DataArrayInt::New();
783   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
784   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
785   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
786   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
787   meshDM1=0;
788   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
789 }
790
791 void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayInt *nodeNeigh, const DataArrayInt *nodeNeighI, MCAuto<DataArrayInt>& cellNeigh, MCAuto<DataArrayInt>& cellNeighIndex) const
792 {
793   if(!nodeNeigh || !nodeNeighI)
794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !");
795   checkConsistencyLight();
796   nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated();
797   nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh");
798   nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index");
799   nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length");
800   int nbCells(getNumberOfCells());
801   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin());
802   cellNeigh=DataArrayInt::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayInt::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0);
803   for(int i=0;i<nbCells;i++)
804     {
805       std::set<int> s;
806       for(const int *it=c+ci[i]+1;it!=c+ci[i+1];it++)
807         if(*it>=0)
808           s.insert(ne+nei[*it],ne+nei[*it+1]);
809       s.erase(i);
810       cellNeigh->insertAtTheEnd(s.begin(),s.end());
811       cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples());
812     }
813 }
814
815 /*!
816  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
817  * of MEDCouplingUMesh::computeNeighborsOfCells.
818  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
819  * typically the case to extract a set a neighbours,
820  * excluding a set of meshdim-1 cells in input descending connectivity.
821  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
822  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
823  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
824  * are considered.
825  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
826  *
827  * \param [in] desc descending connectivity array.
828  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
829  * \param [in] revDesc reverse descending connectivity array.
830  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
831  * \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
832  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
833  * \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.
834  */
835 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
836                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
837 {
838   if(!desc || !descIndx || !revDesc || !revDescIndx)
839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
840   const int *descPtr=desc->begin();
841   const int *descIPtr=descIndx->begin();
842   const int *revDescPtr=revDesc->begin();
843   const int *revDescIPtr=revDescIndx->begin();
844   //
845   int nbCells=descIndx->getNumberOfTuples()-1;
846   MCAuto<DataArrayInt> out0=DataArrayInt::New();
847   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
848   int *out1Ptr=out1->getPointer();
849   *out1Ptr++=0;
850   out0->reserve(desc->getNumberOfTuples());
851   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
852     {
853       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
854         {
855           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
856           s.erase(i);
857           out0->insertAtTheEnd(s.begin(),s.end());
858         }
859       *out1Ptr=out0->getNumberOfTuples();
860     }
861   neighbors=out0.retn();
862   neighborsIndx=out1.retn();
863 }
864
865 /*!
866  * Explodes \a this into edges whatever its dimension.
867  */
868 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::explodeIntoEdges(MCAuto<DataArrayInt>& desc, MCAuto<DataArrayInt>& descIndex, MCAuto<DataArrayInt>& revDesc, MCAuto<DataArrayInt>& revDescIndx) const
869 {
870   checkFullyDefined();
871   int mdim(getMeshDimension());
872   desc=DataArrayInt::New(); descIndex=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
873   MCAuto<MEDCouplingUMesh> mesh1D;
874   switch(mdim)
875   {
876     case 3:
877       {
878         mesh1D=explode3DMeshTo1D(desc,descIndex,revDesc,revDescIndx);
879         break;
880       }
881     case 2:
882       {
883         mesh1D=buildDescendingConnectivity(desc,descIndex,revDesc,revDescIndx);
884         break;
885       }
886     default:
887       {
888         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2] !");
889       }
890   }
891   return mesh1D;
892 }
893
894 /*!
895  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
896  * For speed reasons no check of this will be done. This method calls
897  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
898  * This method lists node by node in \b this which are its neighbors. To compute the result
899  * only connectivities are considered.
900  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
901  *
902  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
903  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
904  * parameter allows to select the right part in this array (\ref numbering-indirect).
905  * The number of tuples is equal to the last values in \b neighborsIndx.
906  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
907  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
908  * 
909  * \sa MEDCouplingUMesh::computeEnlargedNeighborsOfNodes
910  */
911 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
912 {
913   checkFullyDefined();
914   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
915   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
916   MCConstAuto<MEDCouplingUMesh> mesh1D;
917   switch(mdim)
918   {
919     case 3:
920       {
921         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
922         break;
923       }
924     case 2:
925       {
926         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
927         break;
928       }
929     case 1:
930       {
931         mesh1D.takeRef(this);
932         break;
933       }
934     default:
935       {
936         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
937       }
938   }
939   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
940   mesh1D->getReverseNodalConnectivity(desc,descIndx);
941   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
942   ret0->alloc(desc->getNumberOfTuples(),1);
943   int *r0Pt(ret0->getPointer());
944   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
945   for(int i=0;i<nbNodes;i++,rni++)
946     {
947       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
948         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
949     }
950   neighbors=ret0.retn();
951   neighborsIdx=descIndx.retn();
952 }
953
954 /*!
955  * Computes enlarged neighbors for each nodes in \a this. The behavior of this method is close to MEDCouplingUMesh::computeNeighborsOfNodes except that the neighborhood of each node is wider here.
956  * A node j is considered to be in the neighborhood of i if and only if there is a cell in \a this containing in its nodal connectivity both i and j.
957  * This method is useful to find ghost cells of a part of a mesh with a code based on fields on nodes.
958  * 
959  * \sa MEDCouplingUMesh::computeNeighborsOfNodes
960  */
961 void MEDCouplingUMesh::computeEnlargedNeighborsOfNodes(MCAuto<DataArrayInt> &neighbors, MCAuto<DataArrayInt>& neighborsIdx) const
962 {
963   checkFullyDefined();
964   int nbOfNodes(getNumberOfNodes());
965   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
966   int nbOfCells(getNumberOfCells());
967   std::vector< std::set<int> > st0(nbOfNodes);
968   for(int eltId=0;eltId<nbOfCells;eltId++)
969     {
970       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
971       std::set<int> s(strtNdlConnOfCurCell,endNdlConnOfCurCell); s.erase(-1); //for polyhedrons
972       for(std::set<int>::const_iterator iter2=s.begin();iter2!=s.end();iter2++)
973         st0[*iter2].insert(s.begin(),s.end());
974     }
975   neighborsIdx=DataArrayInt::New(); neighborsIdx->alloc(nbOfNodes+1,1); neighborsIdx->setIJ(0,0,0);
976   {
977     int *neighIdx(neighborsIdx->getPointer());
978     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++)
979       {
980         if ((*it).empty())
981           neighIdx[1]=neighIdx[0];
982         else
983           neighIdx[1]=neighIdx[0]+(*it).size()-1;
984       }
985   }
986   neighbors=DataArrayInt::New(); neighbors->alloc(neighborsIdx->back(),1);
987   {
988     const int *neighIdx(neighborsIdx->begin());
989     int *neigh(neighbors->getPointer()),nodeId(0);
990     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++,nodeId++)
991       {
992         std::set<int> s(*it); s.erase(nodeId);
993         std::copy(s.begin(),s.end(),neigh+*neighIdx);
994       }
995   }
996 }
997
998 /*!
999  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1000  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1001  * array of cell ids. Pay attention that after conversion all algorithms work slower
1002  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1003  * conversion due presence of invalid ids in the array of cells to convert, as a
1004  * result \a this mesh contains some already converted elements. In this case the 2D
1005  * mesh remains valid but 3D mesh becomes \b inconsistent!
1006  *  \warning This method can significantly modify the order of geometric types in \a this,
1007  *          hence, to write this mesh to the MED file, its cells must be sorted using
1008  *          sortCellsInMEDFileFrmt().
1009  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1010  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1011  *         cellIdsToConvertBg.
1012  *  \throw If the coordinates array is not set.
1013  *  \throw If the nodal connectivity of cells is node defined.
1014  *  \throw If dimension of \a this mesh is not either 2 or 3.
1015  *
1016  *  \if ENABLE_EXAMPLES
1017  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1018  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1019  *  \endif
1020  */
1021 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1022 {
1023   checkFullyDefined();
1024   int dim=getMeshDimension();
1025   if(dim<2 || dim>3)
1026     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1027   int nbOfCells(getNumberOfCells());
1028   if(dim==2)
1029     {
1030       const int *connIndex=_nodal_connec_index->begin();
1031       int *conn=_nodal_connec->getPointer();
1032       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1033         {
1034           if(*iter>=0 && *iter<nbOfCells)
1035             {
1036               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1037               if(!cm.isQuadratic())
1038                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1039               else
1040                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1041             }
1042           else
1043             {
1044               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1045               oss << " in range [0," << nbOfCells << ") !";
1046               throw INTERP_KERNEL::Exception(oss.str());
1047             }
1048         }
1049     }
1050   else
1051     {
1052       int *connIndex(_nodal_connec_index->getPointer());
1053       const int *connOld(_nodal_connec->getConstPointer());
1054       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1055       std::vector<bool> toBeDone(nbOfCells,false);
1056       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1057         {
1058           if(*iter>=0 && *iter<nbOfCells)
1059             toBeDone[*iter]=true;
1060           else
1061             {
1062               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1063               oss << " in range [0," << nbOfCells << ") !";
1064               throw INTERP_KERNEL::Exception(oss.str());
1065             }
1066         }
1067       for(int cellId=0;cellId<nbOfCells;cellId++)
1068         {
1069           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1070           int lgthOld(posP1-pos-1);
1071           if(toBeDone[cellId])
1072             {
1073               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1074               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1075               int *tmp(new int[nbOfFaces*lgthOld+1]);
1076               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1077               for(unsigned j=0;j<nbOfFaces;j++)
1078                 {
1079                   INTERP_KERNEL::NormalizedCellType type;
1080                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1081                   work+=offset;
1082                   *work++=-1;
1083                 }
1084               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1085               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1086               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1087               delete [] tmp;
1088             }
1089           else
1090             {
1091               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1092               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1093             }
1094         }
1095       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1096     }
1097   computeTypes();
1098 }
1099
1100 /*!
1101  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1102  * polyhedrons (if \a this is a 3D mesh).
1103  *  \warning As this method is purely for user-friendliness and no optimization is
1104  *          done to avoid construction of a useless vector, this method can be costly
1105  *          in memory.
1106  *  \throw If the coordinates array is not set.
1107  *  \throw If the nodal connectivity of cells is node defined.
1108  *  \throw If dimension of \a this mesh is not either 2 or 3.
1109  */
1110 void MEDCouplingUMesh::convertAllToPoly()
1111 {
1112   int nbOfCells=getNumberOfCells();
1113   std::vector<int> cellIds(nbOfCells);
1114   for(int i=0;i<nbOfCells;i++)
1115     cellIds[i]=i;
1116   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1117 }
1118
1119 /*!
1120  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1121  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1122  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1123  * base facet of the volume and the second half of nodes describes an opposite facet
1124  * having the same number of nodes as the base one. This method converts such
1125  * connectivity to a valid polyhedral format where connectivity of each facet is
1126  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1127  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1128  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1129  * a correct orientation of the first facet of a polyhedron, else orientation of a
1130  * corrected cell is reverse.<br>
1131  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1132  * it releases the user from boring description of polyhedra connectivity in the valid
1133  * format.
1134  *  \throw If \a this->getMeshDimension() != 3.
1135  *  \throw If \a this->getSpaceDimension() != 3.
1136  *  \throw If the nodal connectivity of cells is not defined.
1137  *  \throw If the coordinates array is not set.
1138  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1139  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1140  *
1141  *  \if ENABLE_EXAMPLES
1142  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1143  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1144  *  \endif
1145  */
1146 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1147 {
1148   checkFullyDefined();
1149   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1150     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1151   int nbOfCells=getNumberOfCells();
1152   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1153   newCi->alloc(nbOfCells+1,1);
1154   int *newci=newCi->getPointer();
1155   const int *ci=_nodal_connec_index->getConstPointer();
1156   const int *c=_nodal_connec->getConstPointer();
1157   newci[0]=0;
1158   for(int i=0;i<nbOfCells;i++)
1159     {
1160       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1161       if(type==INTERP_KERNEL::NORM_POLYHED)
1162         {
1163           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1164             {
1165               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1166               throw INTERP_KERNEL::Exception(oss.str());
1167             }
1168           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1169           if(n2%2!=0)
1170             {
1171               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 !";
1172               throw INTERP_KERNEL::Exception(oss.str());
1173             }
1174           int n1=(int)(n2/2);
1175           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)
1176         }
1177       else
1178         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1179     }
1180   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1181   newC->alloc(newci[nbOfCells],1);
1182   int *newc=newC->getPointer();
1183   for(int i=0;i<nbOfCells;i++)
1184     {
1185       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1186       if(type==INTERP_KERNEL::NORM_POLYHED)
1187         {
1188           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1189           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1190           *newc++=-1;
1191           for(std::size_t j=0;j<n1;j++)
1192             {
1193               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1194               newc[n1+5*j]=-1;
1195               newc[n1+5*j+1]=c[ci[i]+1+j];
1196               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1197               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1198               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1199             }
1200           newc+=n1*6;
1201         }
1202       else
1203         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1204     }
1205   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1206   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1207 }
1208
1209
1210 /*!
1211  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1212  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1213  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1214  *          to write this mesh to the MED file, its cells must be sorted using
1215  *          sortCellsInMEDFileFrmt().
1216  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1217  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1218  * \return \c true if at least one cell has been converted, \c false else. In the
1219  *         last case the nodal connectivity remains unchanged.
1220  * \throw If the coordinates array is not set.
1221  * \throw If the nodal connectivity of cells is not defined.
1222  * \throw If \a this->getMeshDimension() < 0.
1223  */
1224 bool MEDCouplingUMesh::unPolyze()
1225 {
1226   checkFullyDefined();
1227   int mdim=getMeshDimension();
1228   if(mdim<0)
1229     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1230   if(mdim<=1)
1231     return false;
1232   int nbOfCells=getNumberOfCells();
1233   if(nbOfCells<1)
1234     return false;
1235   int initMeshLgth=getNodalConnectivityArrayLen();
1236   int *conn=_nodal_connec->getPointer();
1237   int *index=_nodal_connec_index->getPointer();
1238   int posOfCurCell=0;
1239   int newPos=0;
1240   int lgthOfCurCell;
1241   bool ret=false;
1242   for(int i=0;i<nbOfCells;i++)
1243     {
1244       lgthOfCurCell=index[i+1]-posOfCurCell;
1245       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1246       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1247       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1248       int newLgth;
1249       if(cm.isDynamic())
1250         {
1251           switch(cm.getDimension())
1252           {
1253             case 2:
1254               {
1255                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1256                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1257                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1258                 break;
1259               }
1260             case 3:
1261               {
1262                 int nbOfFaces,lgthOfPolyhConn;
1263                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1264                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1265                 break;
1266               }
1267             case 1:
1268               {
1269                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1270                 break;
1271               }
1272           }
1273           ret=ret || (newType!=type);
1274           conn[newPos]=newType;
1275           newPos+=newLgth+1;
1276           posOfCurCell=index[i+1];
1277           index[i+1]=newPos;
1278         }
1279       else
1280         {
1281           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1282           newPos+=lgthOfCurCell;
1283           posOfCurCell+=lgthOfCurCell;
1284           index[i+1]=newPos;
1285         }
1286     }
1287   if(newPos!=initMeshLgth)
1288     _nodal_connec->reAlloc(newPos);
1289   if(ret)
1290     computeTypes();
1291   return ret;
1292 }
1293
1294 /*!
1295  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1296  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1297  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1298  *
1299  * \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 
1300  *             precision.
1301  */
1302 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1303 {
1304   checkFullyDefined();
1305   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1306     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1307   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1308   coords->recenterForMaxPrecision(eps);
1309   //
1310   int nbOfCells=getNumberOfCells();
1311   const int *conn=_nodal_connec->getConstPointer();
1312   const int *index=_nodal_connec_index->getConstPointer();
1313   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1314   connINew->alloc(nbOfCells+1,1);
1315   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1316   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1317   MCAuto<DataArrayInt> E_Fi(DataArrayInt::New()), E_F(DataArrayInt::New()), F_Ei(DataArrayInt::New()), F_E(DataArrayInt::New());
1318   MCAuto<MEDCouplingUMesh> m_faces(buildDescendingConnectivity(E_F, E_Fi, F_E, F_Ei));
1319   bool changed=false;
1320   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1321     {
1322       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1323         {
1324           SimplifyPolyhedronCell(eps,coords, i,connNew, m_faces, E_Fi, E_F, F_Ei, F_E);
1325           changed=true;
1326         }
1327       else
1328         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1329       *connINewPtr=connNew->getNumberOfTuples();
1330     }
1331   if(changed)
1332     setConnectivity(connNew,connINew,false);
1333 }
1334
1335 /*!
1336  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1337  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1338  * the format of the returned DataArrayInt instance.
1339  * 
1340  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1341  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1342  */
1343 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1344 {
1345   checkConnectivityFullyDefined();
1346   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1347   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1348   std::vector<bool> retS(maxElt,false);
1349   computeNodeIdsAlg(retS);
1350   return DataArrayInt::BuildListOfSwitchedOn(retS);
1351 }
1352
1353 /*!
1354  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1355  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1356  */
1357 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1358 {
1359   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1360   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1361   for(int i=0;i<nbOfCells;i++)
1362     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1363       if(conn[j]>=0)
1364         {
1365           if(conn[j]<nbOfNodes)
1366             nodeIdsInUse[conn[j]]=true;
1367           else
1368             {
1369               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1370               throw INTERP_KERNEL::Exception(oss.str());
1371             }
1372         }
1373 }
1374
1375 /// @cond INTERNAL
1376
1377 struct MEDCouplingAccVisit
1378 {
1379   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1380   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1381   int _new_nb_of_nodes;
1382 };
1383
1384 /// @endcond
1385
1386 /*!
1387  * Finds nodes not used in any cell and returns an array giving a new id to every node
1388  * by excluding the unused nodes, for which the array holds -1. The result array is
1389  * a mapping in "Old to New" mode. 
1390  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1391  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1392  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1393  *          if the node is unused or a new id else. The caller is to delete this
1394  *          array using decrRef() as it is no more needed.  
1395  *  \throw If the coordinates array is not set.
1396  *  \throw If the nodal connectivity of cells is not defined.
1397  *  \throw If the nodal connectivity includes an invalid id.
1398  *
1399  *  \if ENABLE_EXAMPLES
1400  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1401  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1402  *  \endif
1403  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1404  */
1405 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1406 {
1407   nbrOfNodesInUse=-1;
1408   int nbOfNodes(getNumberOfNodes());
1409   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1410   ret->alloc(nbOfNodes,1);
1411   int *traducer=ret->getPointer();
1412   std::fill(traducer,traducer+nbOfNodes,-1);
1413   int nbOfCells=getNumberOfCells();
1414   const int *connIndex=_nodal_connec_index->getConstPointer();
1415   const int *conn=_nodal_connec->getConstPointer();
1416   for(int i=0;i<nbOfCells;i++)
1417     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1418       if(conn[j]>=0)
1419         {
1420           if(conn[j]<nbOfNodes)
1421             traducer[conn[j]]=1;
1422           else
1423             {
1424               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1425               throw INTERP_KERNEL::Exception(oss.str());
1426             }
1427         }
1428   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1429   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1430   return ret.retn();
1431 }
1432
1433 /*!
1434  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1435  * For each cell in \b this the number of nodes constituting cell is computed.
1436  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1437  * So for pohyhedrons some nodes can be counted several times in the returned result.
1438  * 
1439  * \return a newly allocated array
1440  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1441  */
1442 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1443 {
1444   checkConnectivityFullyDefined();
1445   int nbOfCells=getNumberOfCells();
1446   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1447   ret->alloc(nbOfCells,1);
1448   int *retPtr=ret->getPointer();
1449   const int *conn=getNodalConnectivity()->getConstPointer();
1450   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1451   for(int i=0;i<nbOfCells;i++,retPtr++)
1452     {
1453       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1454         *retPtr=connI[i+1]-connI[i]-1;
1455       else
1456         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1457     }
1458   return ret.retn();
1459 }
1460
1461 /*!
1462  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1463  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1464  *
1465  * \return DataArrayInt * - new object to be deallocated by the caller.
1466  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1467  */
1468 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1469 {
1470   checkConnectivityFullyDefined();
1471   int nbOfCells=getNumberOfCells();
1472   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1473   ret->alloc(nbOfCells,1);
1474   int *retPtr=ret->getPointer();
1475   const int *conn=getNodalConnectivity()->getConstPointer();
1476   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1477   for(int i=0;i<nbOfCells;i++,retPtr++)
1478     {
1479       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1480       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1481         *retPtr=(int)s.size();
1482       else
1483         {
1484           s.erase(-1);
1485           *retPtr=(int)s.size();
1486         }
1487     }
1488   return ret.retn();
1489 }
1490
1491 /*!
1492  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1494  * 
1495  * \return a newly allocated array
1496  */
1497 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1498 {
1499   checkConnectivityFullyDefined();
1500   int nbOfCells=getNumberOfCells();
1501   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1502   ret->alloc(nbOfCells,1);
1503   int *retPtr=ret->getPointer();
1504   const int *conn=getNodalConnectivity()->getConstPointer();
1505   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1506   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1507     {
1508       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1509       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1510     }
1511   return ret.retn();
1512 }
1513
1514 /*!
1515  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1516  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1517  * array mean that the corresponding old node is no more used. 
1518  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1519  *           this->getNumberOfNodes() before call of this method. The caller is to
1520  *           delete this array using decrRef() as it is no more needed. 
1521  *  \throw If the coordinates array is not set.
1522  *  \throw If the nodal connectivity of cells is not defined.
1523  *  \throw If the nodal connectivity includes an invalid id.
1524  *  \sa areAllNodesFetched
1525  *
1526  *  \if ENABLE_EXAMPLES
1527  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1528  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1529  *  \endif
1530  */
1531 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1532 {
1533   return MEDCouplingPointSet::zipCoordsTraducer();
1534 }
1535
1536 /*!
1537  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1538  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1539  */
1540 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1541 {
1542   switch(compType)
1543   {
1544     case 0:
1545       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1546     case 1:
1547       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1548     case 2:
1549       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1550     case 3:
1551       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1552     case 7:
1553       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1554   }
1555   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1556 }
1557
1558 /*!
1559  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1560  */
1561 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1562 {
1563   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1564     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1565   return 0;
1566 }
1567
1568 /*!
1569  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1570  */
1571 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1572 {
1573   int sz=connI[cell1+1]-connI[cell1];
1574   if(sz==connI[cell2+1]-connI[cell2])
1575     {
1576       if(conn[connI[cell1]]==conn[connI[cell2]])
1577         {
1578           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1579           unsigned dim=cm.getDimension();
1580           if(dim!=3)
1581             {
1582               if(dim!=1)
1583                 {
1584                   int sz1=2*(sz-1);
1585                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1586                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1587                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1588                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1589                   return work!=tmp+sz1?1:0;
1590                 }
1591               else
1592                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1593             }
1594           else
1595             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1596         }
1597     }
1598   return 0;
1599 }
1600
1601 /*!
1602  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1603  */
1604 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1605 {
1606   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1607     {
1608       if(conn[connI[cell1]]==conn[connI[cell2]])
1609         {
1610           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1611           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1612           return s1==s2?1:0;
1613         }
1614     }
1615   return 0;
1616 }
1617
1618 /*!
1619  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1620  */
1621 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1622 {
1623   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1624     {
1625       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1626       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1627       return s1==s2?1:0;
1628     }
1629   return 0;
1630 }
1631
1632 /*!
1633  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1634  */
1635 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1636 {
1637   int sz=connI[cell1+1]-connI[cell1];
1638   if(sz==connI[cell2+1]-connI[cell2])
1639     {
1640       if(conn[connI[cell1]]==conn[connI[cell2]])
1641         {
1642           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1643           unsigned dim=cm.getDimension();
1644           if(dim!=3)
1645             {
1646               if(dim!=1)
1647                 {
1648                   int sz1=2*(sz-1);
1649                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1650                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1651                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1652                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1653                   if(work!=tmp+sz1)
1654                     return 1;
1655                   else
1656                     {
1657                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1658                       std::reverse_iterator<int *> it2((int *)tmp);
1659                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1660                         return 2;
1661                       else
1662                         return 0;
1663                     }
1664
1665                   return work!=tmp+sz1?1:0;
1666                 }
1667               else
1668                 {//case of SEG2 and SEG3
1669                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1670                     return 1;
1671                   if(!cm.isQuadratic())
1672                     {
1673                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1674                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1675                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1676                         return 2;
1677                       return 0;
1678                     }
1679                   else
1680                     {
1681                       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])
1682                         return 2;
1683                       return 0;
1684                     }
1685                 }
1686             }
1687           else
1688             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1689         }
1690     }
1691   return 0;
1692 }
1693
1694
1695 /*!
1696  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1697  * by \a compType.
1698  * This method keeps the coordiantes of \a this. This method is time consuming.
1699  *
1700  * \param [in] compType input specifying the technique used to compare cells each other.
1701  *   - 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.
1702  *   - 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)
1703  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1704  *   - 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
1705  * can be used for users not sensitive to orientation of cell
1706  * \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.
1707  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1708  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1709  * \return the correspondence array old to new in a newly allocated array.
1710  * 
1711  */
1712 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1713 {
1714   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1715   getReverseNodalConnectivity(revNodal,revNodalI);
1716   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1717 }
1718
1719 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1720                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1721 {
1722   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1723   int nbOfCells=nodalI->getNumberOfTuples()-1;
1724   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1725   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1726   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1727   std::vector<bool> isFetched(nbOfCells,false);
1728   if(startCellId==0)
1729     {
1730       for(int i=0;i<nbOfCells;i++)
1731         {
1732           if(!isFetched[i])
1733             {
1734               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1735               std::vector<int> v,v2;
1736               if(connOfNode!=connPtr+connIPtr[i+1])
1737                 {
1738                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1739                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1740                   connOfNode++;
1741                 }
1742               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1743                 if(*connOfNode>=0)
1744                   {
1745                     v=v2;
1746                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1747                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1748                     v2.resize(std::distance(v2.begin(),it));
1749                   }
1750               if(v2.size()>1)
1751                 {
1752                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1753                     {
1754                       int pos=commonCellsI->back();
1755                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1756                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1757                         isFetched[*it]=true;
1758                     }
1759                 }
1760             }
1761         }
1762     }
1763   else
1764     {
1765       for(int i=startCellId;i<nbOfCells;i++)
1766         {
1767           if(!isFetched[i])
1768             {
1769               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1770               std::vector<int> v,v2;
1771               if(connOfNode!=connPtr+connIPtr[i+1])
1772                 {
1773                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1774                   connOfNode++;
1775                 }
1776               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1777                 if(*connOfNode>=0)
1778                   {
1779                     v=v2;
1780                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1781                     v2.resize(std::distance(v2.begin(),it));
1782                   }
1783               if(v2.size()>1)
1784                 {
1785                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1786                     {
1787                       int pos=commonCellsI->back();
1788                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1789                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1790                         isFetched[*it]=true;
1791                     }
1792                 }
1793             }
1794         }
1795     }
1796   commonCellsArr=commonCells.retn();
1797   commonCellsIArr=commonCellsI.retn();
1798 }
1799
1800 /*!
1801  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1802  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1803  * than \a this->getNumberOfCells() in the returned array means that there is no
1804  * corresponding cell in \a this mesh.
1805  * It is expected that \a this and \a other meshes share the same node coordinates
1806  * array, if it is not so an exception is thrown. 
1807  *  \param [in] other - the mesh to compare with.
1808  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1809  *         valid values [0,1,2], see zipConnectivityTraducer().
1810  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1811  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1812  *         values. The caller is to delete this array using
1813  *         decrRef() as it is no more needed.
1814  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1815  *         mesh.
1816  *
1817  *  \if ENABLE_EXAMPLES
1818  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1819  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1820  *  \endif
1821  *  \sa checkDeepEquivalOnSameNodesWith()
1822  *  \sa checkGeoEquivalWith()
1823  */
1824 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1825 {
1826   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1827   int nbOfCells=getNumberOfCells();
1828   static const int possibleCompType[]={0,1,2};
1829   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1830     {
1831       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1832       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1833       oss << " !";
1834       throw INTERP_KERNEL::Exception(oss.str());
1835     }
1836   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1837   arr=o2n->subArray(nbOfCells);
1838   arr->setName(other->getName());
1839   int tmp;
1840   if(other->getNumberOfCells()==0)
1841     return true;
1842   return arr->getMaxValue(tmp)<nbOfCells;
1843 }
1844
1845 /*!
1846  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1847  * This method tries to determine if \b other is fully included in \b this.
1848  * The main difference is that this method is not expected to throw exception.
1849  * This method has two outputs :
1850  *
1851  * \param other other mesh
1852  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1853  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1854  */
1855 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1856 {
1857   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1858   DataArrayInt *commonCells=0,*commonCellsI=0;
1859   int thisNbCells=getNumberOfCells();
1860   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1861   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1862   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1863   int otherNbCells=other->getNumberOfCells();
1864   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1865   arr2->alloc(otherNbCells,1);
1866   arr2->fillWithZero();
1867   int *arr2Ptr=arr2->getPointer();
1868   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1869   for(int i=0;i<nbOfCommon;i++)
1870     {
1871       int start=commonCellsPtr[commonCellsIPtr[i]];
1872       if(start<thisNbCells)
1873         {
1874           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1875             {
1876               int sig=commonCellsPtr[j]>0?1:-1;
1877               int val=std::abs(commonCellsPtr[j])-1;
1878               if(val>=thisNbCells)
1879                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1880             }
1881         }
1882     }
1883   arr2->setName(other->getName());
1884   if(arr2->presenceOfValue(0))
1885     return false;
1886   arr=arr2.retn();
1887   return true;
1888 }
1889
1890 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1891 {
1892   if(!other)
1893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1894   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1895   if(!otherC)
1896     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1897   std::vector<const MEDCouplingUMesh *> ms(2);
1898   ms[0]=this;
1899   ms[1]=otherC;
1900   return MergeUMeshesOnSameCoords(ms);
1901 }
1902
1903 /*!
1904  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1905  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1906  * cellIds is not given explicitly but by a range python like.
1907  * 
1908  * \param start
1909  * \param end
1910  * \param step
1911  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1912  * \return a newly allocated
1913  * 
1914  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1915  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1916  */
1917 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
1918 {
1919   if(getMeshDimension()!=-1)
1920     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
1921   else
1922     {
1923       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
1924       if(newNbOfCells!=1)
1925         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1926       if(start!=0)
1927         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1928       incrRef();
1929       return const_cast<MEDCouplingUMesh *>(this);
1930     }
1931 }
1932
1933 /*!
1934  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1935  * The result mesh shares or not the node coordinates array with \a this mesh depending
1936  * on \a keepCoords parameter.
1937  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1938  *           to write this mesh to the MED file, its cells must be sorted using
1939  *           sortCellsInMEDFileFrmt().
1940  *  \param [in] begin - an array of cell ids to include to the new mesh.
1941  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1942  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1943  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1944  *         by calling zipCoords().
1945  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
1946  *         to delete this mesh using decrRef() as it is no more needed. 
1947  *  \throw If the coordinates array is not set.
1948  *  \throw If the nodal connectivity of cells is not defined.
1949  *  \throw If any cell id in the array \a begin is not valid.
1950  *
1951  *  \if ENABLE_EXAMPLES
1952  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1953  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1954  *  \endif
1955  */
1956 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1957 {
1958   if(getMeshDimension()!=-1)
1959     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
1960   else
1961     {
1962       if(end-begin!=1)
1963         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1964       if(begin[0]!=0)
1965         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1966       incrRef();
1967       return const_cast<MEDCouplingUMesh *>(this);
1968     }
1969 }
1970
1971 /*!
1972  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1973  *
1974  * 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.
1975  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1976  * The number of cells of \b this will remain the same with this method.
1977  *
1978  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
1979  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
1980  * \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 ).
1981  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1982  */
1983 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1984 {
1985   checkConnectivityFullyDefined();
1986   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1987   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1989   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1990     {
1991       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1992       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1993       throw INTERP_KERNEL::Exception(oss.str());
1994     }
1995   std::size_t nbOfCellsToModify(std::distance(cellIdsBg,cellIdsEnd));
1996   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1997     {
1998       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1999       throw INTERP_KERNEL::Exception(oss.str());
2000     }
2001   std::size_t nbOfCells(getNumberOfCells());
2002   bool easyAssign(true);
2003   const int *connI(_nodal_connec_index->begin());
2004   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->begin();
2005   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2006     {
2007       if(*it>=0 && *it<(int)nbOfCells)
2008         {
2009           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2010         }
2011       else
2012         {
2013           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2014           throw INTERP_KERNEL::Exception(oss.str());
2015         }
2016     }
2017   if(easyAssign)
2018     {
2019       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2020       computeTypes();
2021     }
2022   else
2023     {
2024       DataArrayInt *arrOut=0,*arrIOut=0;
2025       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2026                                                arrOut,arrIOut);
2027       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2028       setConnectivity(arrOut,arrIOut,true);
2029     }
2030 }
2031
2032 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2033 {
2034   checkConnectivityFullyDefined();
2035   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2036   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2037     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2038   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2039     {
2040       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2041       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2042       throw INTERP_KERNEL::Exception(oss.str());
2043     }
2044   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2045   if(nbOfCellsToModify!=(int)otherOnSameCoordsThanThis.getNumberOfCells())
2046     {
2047       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2048       throw INTERP_KERNEL::Exception(oss.str());
2049     }
2050   int nbOfCells=getNumberOfCells();
2051   bool easyAssign=true;
2052   const int *connI=_nodal_connec_index->getConstPointer();
2053   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2054   int it=start;
2055   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2056     {
2057       if(it>=0 && it<nbOfCells)
2058         {
2059           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2060         }
2061       else
2062         {
2063           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2064           throw INTERP_KERNEL::Exception(oss.str());
2065         }
2066     }
2067   if(easyAssign)
2068     {
2069       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2070       computeTypes();
2071     }
2072   else
2073     {
2074       DataArrayInt *arrOut=0,*arrIOut=0;
2075       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2076                                                 arrOut,arrIOut);
2077       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2078       setConnectivity(arrOut,arrIOut,true);
2079     }
2080 }                      
2081
2082
2083 /*!
2084  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2085  * this->getMeshDimension(), that bound some cells of \a this mesh.
2086  * The cells of lower dimension to include to the result mesh are selected basing on
2087  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2088  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2089  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2090  * created mesh shares the node coordinates array with \a this mesh. 
2091  *  \param [in] begin - the array of node ids.
2092  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2093  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2094  *         array \a begin are added, else cells whose any node is in the
2095  *         array \a begin are added.
2096  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2097  *         to delete this mesh using decrRef() as it is no more needed. 
2098  *  \throw If the coordinates array is not set.
2099  *  \throw If the nodal connectivity of cells is not defined.
2100  *  \throw If any node id in \a begin is not valid.
2101  *
2102  *  \if ENABLE_EXAMPLES
2103  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2104  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2105  *  \endif
2106  */
2107 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2108 {
2109   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2110   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2111   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2112   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2113   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2114 }
2115
2116 /*!
2117  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2118  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2119  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2120  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2121  *         by calling zipCoords().
2122  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2123  *         to delete this mesh using decrRef() as it is no more needed. 
2124  *  \throw If the coordinates array is not set.
2125  *  \throw If the nodal connectivity of cells is not defined.
2126  *
2127  *  \if ENABLE_EXAMPLES
2128  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2129  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2130  *  \endif
2131  */
2132 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2133 {
2134   DataArrayInt *desc=DataArrayInt::New();
2135   DataArrayInt *descIndx=DataArrayInt::New();
2136   DataArrayInt *revDesc=DataArrayInt::New();
2137   DataArrayInt *revDescIndx=DataArrayInt::New();
2138   //
2139   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2140   revDesc->decrRef();
2141   desc->decrRef();
2142   descIndx->decrRef();
2143   int nbOfCells=meshDM1->getNumberOfCells();
2144   const int *revDescIndxC=revDescIndx->getConstPointer();
2145   std::vector<int> boundaryCells;
2146   for(int i=0;i<nbOfCells;i++)
2147     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2148       boundaryCells.push_back(i);
2149   revDescIndx->decrRef();
2150   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2151   return ret;
2152 }
2153
2154 /*!
2155  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2156  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2157  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2158  */
2159 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2160 {
2161   checkFullyDefined();
2162   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2163   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2164   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2165   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2166   //
2167   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2168   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2169   //
2170   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2171   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2172   const int *revDescPtr=revDesc->getConstPointer();
2173   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2174   int nbOfCells=getNumberOfCells();
2175   std::vector<bool> ret1(nbOfCells,false);
2176   int sz=0;
2177   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2178     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2179       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2180   //
2181   DataArrayInt *ret2=DataArrayInt::New();
2182   ret2->alloc(sz,1);
2183   int *ret2Ptr=ret2->getPointer();
2184   sz=0;
2185   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2186     if(*it)
2187       *ret2Ptr++=sz;
2188   ret2->setName("BoundaryCells");
2189   return ret2;
2190 }
2191
2192 /*!
2193  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2194  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2195  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2196  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2197  *
2198  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2199  * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2200  * equals a cell in \b otherDimM1OnSameCoords.
2201  *
2202  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2203  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2204  *
2205  * \param [in] otherDimM1OnSameCoords
2206  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2207  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2208  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2209  */
2210 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2211 {
2212   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2213     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2214   checkConnectivityFullyDefined();
2215   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2216   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2218   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2219   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2220   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2221   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2222   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2223   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2224   DataArrayInt *idsOtherInConsti=0;
2225   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2226   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2227   if(!b)
2228     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2229   std::set<int> s1;
2230   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2231     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2232   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2233   s1arr_renum1->sort();
2234   cellIdsRk0=s0arr.retn();
2235   //cellIdsRk1=s_renum1.retn();
2236   cellIdsRk1=s1arr_renum1.retn();
2237 }
2238
2239 /*!
2240  * 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
2241  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2242  * 
2243  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2244  */
2245 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2246 {
2247   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2248   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2249   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2250   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2251   //
2252   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2253   revDesc=0; desc=0; descIndx=0;
2254   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2255   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2256   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2257 }
2258
2259 /*!
2260  * Finds nodes lying on the boundary of \a this mesh.
2261  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2262  *          nodes. The caller is to delete this array using decrRef() as it is no
2263  *          more needed.
2264  *  \throw If the coordinates array is not set.
2265  *  \throw If the nodal connectivity of cells is node defined.
2266  *
2267  *  \if ENABLE_EXAMPLES
2268  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2269  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2270  *  \endif
2271  */
2272 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2273 {
2274   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2275   return skin->computeFetchedNodeIds();
2276 }
2277
2278 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2279 {
2280   incrRef();
2281   return const_cast<MEDCouplingUMesh *>(this);
2282 }
2283
2284 /*!
2285  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2286  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2287  * 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.
2288  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considered as needed to be duplicated.
2289  * 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.
2290  *
2291  * \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
2292  *             parameter is altered during the call.
2293  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2294  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2295  * \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.
2296  *
2297  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2298  */
2299 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2300                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2301 {
2302   typedef MCAuto<DataArrayInt> DAInt;
2303   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2304
2305   checkFullyDefined();
2306   otherDimM1OnSameCoords.checkFullyDefined();
2307   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2308     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2309   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2310     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2311
2312   // Checking star-shaped M1 group:
2313   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2314   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2315   DAInt dsi = rdit0->deltaShiftIndex();
2316   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2317   if(idsTmp0->getNumberOfTuples())
2318     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2319   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2320
2321   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2322   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2323   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2324   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2325   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2326   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2327   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2328   dsi = rdit0->deltaShiftIndex();
2329   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2330   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2331   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2332   // In 3D, some points on the boundary of M0 still need duplication:
2333   DAInt notDup = 0;
2334   if (getMeshDimension() == 3)
2335     {
2336       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2337       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2338       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2339       DataArrayInt * corresp=0;
2340       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2341       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2342       corresp->decrRef();
2343       if (validIds->getNumberOfTuples())
2344         {
2345           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2346           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2347           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2348           notDup = xtrem->buildSubstraction(fNodes1);
2349         }
2350       else
2351         notDup = xtrem->buildSubstraction(fNodes);
2352     }
2353   else
2354     notDup = xtrem->buildSubstraction(fNodes);
2355
2356   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2357   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2358   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2359   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2360
2361   //
2362   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2363   int nCells2 = m0Part2->getNumberOfCells();
2364   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2365   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2366
2367   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2368   DataArrayInt *tmp00=0,*tmp11=0;
2369   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2370   DAInt neighInit00(tmp00);
2371   DAInt neighIInit00(tmp11);
2372   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2373   DataArrayInt *idsTmp=0;
2374   m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2375   DAInt ids(idsTmp);
2376   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2377   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2378   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2379   DataArrayInt *tmp0=0,*tmp1=0;
2380   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2381   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2382   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2383   DAInt neigh00(tmp0);
2384   DAInt neighI00(tmp1);
2385
2386   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2387   int seed = 0, nIter = 0;
2388   int nIterMax = nCells2+1; // Safety net for the loop
2389   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2390   hitCells->fillWithValue(-1);
2391   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2392   cellsToModifyConn0_torenum->alloc(0,1);
2393   while (nIter < nIterMax)
2394     {
2395       DAInt t = hitCells->findIdsEqual(-1);
2396       if (!t->getNumberOfTuples())
2397         break;
2398       // Connex zone without the crack (to compute the next seed really)
2399       int dnu;
2400       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2401       std::size_t cnt(0);
2402       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2403         hitCells->setIJ(*ptr,0,1);
2404       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2405       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2406       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2407       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2408       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2409       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2410       DAInt intersec = nonHitCells->buildIntersection(comple);
2411       if (intersec->getNumberOfTuples())
2412         { seed = intersec->getIJ(0,0); }
2413       else
2414         { break; }
2415       nIter++;
2416     }
2417   if (nIter >= nIterMax)
2418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2419
2420   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2421   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2422   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2423   //
2424   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2425   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2426   nodeIdsToDuplicate=dupl.retn();
2427 }
2428
2429 /*!
2430  * This method operates a modification of the connectivity and coords in \b this.
2431  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2432  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2433  * More explicitly the renumber array in nodes is not explicitly given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2434  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2435  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2436  * 
2437  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2438  * 
2439  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2440  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2441  */
2442 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2443 {
2444   int nbOfNodes=getNumberOfNodes();
2445   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2446   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2447 }
2448
2449 /*!
2450  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2451  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2452  *
2453  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2454  *
2455  * \sa renumberNodesInConn
2456  */
2457 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2458 {
2459   checkConnectivityFullyDefined();
2460   int *conn(getNodalConnectivity()->getPointer());
2461   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2462   int nbOfCells(getNumberOfCells());
2463   for(int i=0;i<nbOfCells;i++)
2464     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2465       {
2466         int& node=conn[iconn];
2467         if(node>=0)//avoid polyhedron separator
2468           {
2469             node+=offset;
2470           }
2471       }
2472   _nodal_connec->declareAsNew();
2473   updateTime();
2474 }
2475
2476 /*!
2477  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2478  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2479  *  of a big mesh.
2480  */
2481 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2482 {
2483   this->renumberNodesInConnT< INTERP_KERNEL::HashMap<int,int> >(newNodeNumbersO2N);
2484 }
2485
2486 /*!
2487  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2488  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2489  *  of a big mesh.
2490  */
2491 void MEDCouplingUMesh::renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N)
2492 {
2493   this->renumberNodesInConnT< std::map<int,int> >(newNodeNumbersO2N);
2494 }
2495
2496 /*!
2497  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2498  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2499  * This method is a generalization of shiftNodeNumbersInConn().
2500  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2501  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2502  *         this->getNumberOfNodes(), in "Old to New" mode. 
2503  *         See \ref numbering for more info on renumbering modes.
2504  *  \throw If the nodal connectivity of cells is not defined.
2505  *
2506  *  \if ENABLE_EXAMPLES
2507  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2508  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2509  *  \endif
2510  */
2511 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2512 {
2513   checkConnectivityFullyDefined();
2514   int *conn=getNodalConnectivity()->getPointer();
2515   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2516   int nbOfCells(getNumberOfCells());
2517   for(int i=0;i<nbOfCells;i++)
2518     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2519       {
2520         int& node=conn[iconn];
2521         if(node>=0)//avoid polyhedron separator
2522           {
2523             node=newNodeNumbersO2N[node];
2524           }
2525       }
2526   _nodal_connec->declareAsNew();
2527   updateTime();
2528 }
2529
2530 /*!
2531  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2532  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2533  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2534  * 
2535  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2536  */
2537 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2538 {
2539   checkConnectivityFullyDefined();
2540   int *conn=getNodalConnectivity()->getPointer();
2541   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2542   int nbOfCells=getNumberOfCells();
2543   for(int i=0;i<nbOfCells;i++)
2544     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2545       {
2546         int& node=conn[iconn];
2547         if(node>=0)//avoid polyhedron separator
2548           {
2549             node+=delta;
2550           }
2551       }
2552   _nodal_connec->declareAsNew();
2553   updateTime();
2554 }
2555
2556 /*!
2557  * This method operates a modification of the connectivity in \b this.
2558  * 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.
2559  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2560  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2561  * More explicitly the renumber array in nodes is not explicitly given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2562  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2563  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2564  * 
2565  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2566  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2567  * 
2568  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2569  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2570  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2571  */
2572 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2573 {
2574   checkConnectivityFullyDefined();
2575   std::map<int,int> m;
2576   int val=offset;
2577   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2578     m[*work]=val;
2579   int *conn=getNodalConnectivity()->getPointer();
2580   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2581   int nbOfCells=getNumberOfCells();
2582   for(int i=0;i<nbOfCells;i++)
2583     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2584       {
2585         int& node=conn[iconn];
2586         if(node>=0)//avoid polyhedron separator
2587           {
2588             std::map<int,int>::iterator it=m.find(node);
2589             if(it!=m.end())
2590               node=(*it).second;
2591           }
2592       }
2593   updateTime();
2594 }
2595
2596 /*!
2597  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2598  *
2599  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2600  * After the call of this method the number of cells remains the same as before.
2601  *
2602  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2603  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2604  * be strictly in [0;this->getNumberOfCells()).
2605  *
2606  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2607  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2608  * should be contained in[0;this->getNumberOfCells()).
2609  * 
2610  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2611  * \param check
2612  */
2613 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2614 {
2615   checkConnectivityFullyDefined();
2616   int nbCells=getNumberOfCells();
2617   const int *array=old2NewBg;
2618   if(check)
2619     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2620   //
2621   const int *conn=_nodal_connec->getConstPointer();
2622   const int *connI=_nodal_connec_index->getConstPointer();
2623   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2624   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2625   const int *n2oPtr=n2o->begin();
2626   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2627   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2628   newConn->copyStringInfoFrom(*_nodal_connec);
2629   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2630   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2631   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2632   //
2633   int *newC=newConn->getPointer();
2634   int *newCI=newConnI->getPointer();
2635   int loc=0;
2636   newCI[0]=loc;
2637   for(int i=0;i<nbCells;i++)
2638     {
2639       int pos=n2oPtr[i];
2640       int nbOfElts=connI[pos+1]-connI[pos];
2641       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2642       loc+=nbOfElts;
2643       newCI[i+1]=loc;
2644     }
2645   //
2646   setConnectivity(newConn,newConnI);
2647   if(check)
2648     free(const_cast<int *>(array));
2649 }
2650
2651 /*!
2652  * Finds cells whose bounding boxes intersect a given bounding box.
2653  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2654  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2655  *         zMax (if in 3D). 
2656  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2657  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2658  *         extent of the bounding box of cell to produce an addition to this bounding box.
2659  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2660  *         cells. The caller is to delete this array using decrRef() as it is no more
2661  *         needed. 
2662  *  \throw If the coordinates array is not set.
2663  *  \throw If the nodal connectivity of cells is not defined.
2664  *
2665  *  \if ENABLE_EXAMPLES
2666  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2667  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2668  *  \endif
2669  */
2670 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2671 {
2672   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2673   if(getMeshDimension()==-1)
2674     {
2675       elems->pushBackSilent(0);
2676       return elems.retn();
2677     }
2678   int dim=getSpaceDimension();
2679   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2680   const int* conn      = getNodalConnectivity()->getConstPointer();
2681   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2682   const double* coords = getCoords()->getConstPointer();
2683   int nbOfCells=getNumberOfCells();
2684   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2685     {
2686       for (int i=0; i<dim; i++)
2687         {
2688           elem_bb[i*2]=std::numeric_limits<double>::max();
2689           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2690         }
2691
2692       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2693         {
2694           int node= conn[inode];
2695           if(node>=0)//avoid polyhedron separator
2696             {
2697               for (int idim=0; idim<dim; idim++)
2698                 {
2699                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2700                     {
2701                       elem_bb[idim*2] = coords[node*dim+idim] ;
2702                     }
2703                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2704                     {
2705                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2706                     }
2707                 }
2708             }
2709         }
2710       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2711         elems->pushBackSilent(ielem);
2712     }
2713   return elems.retn();
2714 }
2715
2716 /*!
2717  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2718  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2719  * added in 'elems' parameter.
2720  */
2721 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2722 {
2723   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2724   if(getMeshDimension()==-1)
2725     {
2726       elems->pushBackSilent(0);
2727       return elems.retn();
2728     }
2729   int dim=getSpaceDimension();
2730   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2731   const int* conn      = getNodalConnectivity()->getConstPointer();
2732   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2733   const double* coords = getCoords()->getConstPointer();
2734   int nbOfCells=getNumberOfCells();
2735   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2736     {
2737       for (int i=0; i<dim; i++)
2738         {
2739           elem_bb[i*2]=std::numeric_limits<double>::max();
2740           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2741         }
2742
2743       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2744         {
2745           int node= conn[inode];
2746           if(node>=0)//avoid polyhedron separator
2747             {
2748               for (int idim=0; idim<dim; idim++)
2749                 {
2750                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2751                     {
2752                       elem_bb[idim*2] = coords[node*dim+idim] ;
2753                     }
2754                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2755                     {
2756                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2757                     }
2758                 }
2759             }
2760         }
2761       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2762         elems->pushBackSilent(ielem);
2763     }
2764   return elems.retn();
2765 }
2766
2767 /*!
2768  * Returns a type of a cell by its id.
2769  *  \param [in] cellId - the id of the cell of interest.
2770  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2771  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2772  */
2773 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(std::size_t cellId) const
2774 {
2775   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2776   if(cellId<_nodal_connec_index->getNbOfElems()-1)
2777     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2778   else
2779     {
2780       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2781       throw INTERP_KERNEL::Exception(oss.str());
2782     }
2783 }
2784
2785 /*!
2786  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2787  * This method does not throw exception if geometric type \a type is not in \a this.
2788  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2789  * The coordinates array is not considered here.
2790  *
2791  * \param [in] type the geometric type
2792  * \return cell ids in this having geometric type \a type.
2793  */
2794 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2795 {
2796
2797   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2798   ret->alloc(0,1);
2799   checkConnectivityFullyDefined();
2800   int nbCells=getNumberOfCells();
2801   int mdim=getMeshDimension();
2802   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2803   if(mdim!=(int)cm.getDimension())
2804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2805   const int *ptI=_nodal_connec_index->getConstPointer();
2806   const int *pt=_nodal_connec->getConstPointer();
2807   for(int i=0;i<nbCells;i++)
2808     {
2809       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2810         ret->pushBackSilent(i);
2811     }
2812   return ret.retn();
2813 }
2814
2815 /*!
2816  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2817  */
2818 std::size_t MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2819 {
2820   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2821   std::size_t nbOfCells(getNumberOfCells()),ret(0);
2822   for(std::size_t i=0;i<nbOfCells;i++)
2823     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2824       ret++;
2825   return ret;
2826 }
2827
2828 /*!
2829  * Returns the nodal connectivity of a given cell.
2830  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2831  * all returned node ids can be used in getCoordinatesOfNode().
2832  *  \param [in] cellId - an id of the cell of interest.
2833  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2834  *         cleared before the appending.
2835  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2836  */
2837 void MEDCouplingUMesh::getNodeIdsOfCell(std::size_t cellId, std::vector<int>& conn) const
2838 {
2839   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2840   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2841     if(*w>=0)
2842       conn.push_back(*w);
2843 }
2844
2845 std::string MEDCouplingUMesh::simpleRepr() const
2846 {
2847   static const char msg0[]="No coordinates specified !";
2848   std::ostringstream ret;
2849   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2850   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2851   int tmpp1,tmpp2;
2852   double tt=getTime(tmpp1,tmpp2);
2853   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2854   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2855   if(_mesh_dim>=-1)
2856     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2857   else
2858     { ret << " Mesh dimension has not been set or is invalid !"; }
2859   if(_coords!=0)
2860     {
2861       const int spaceDim=getSpaceDimension();
2862       ret << spaceDim << "\nInfo attached on space dimension : ";
2863       for(int i=0;i<spaceDim;i++)
2864         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2865       ret << "\n";
2866     }
2867   else
2868     ret << msg0 << "\n";
2869   ret << "Number of nodes : ";
2870   if(_coords!=0)
2871     ret << getNumberOfNodes() << "\n";
2872   else
2873     ret << msg0 << "\n";
2874   ret << "Number of cells : ";
2875   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2876     ret << getNumberOfCells() << "\n";
2877   else
2878     ret << "No connectivity specified !" << "\n";
2879   ret << "Cell types present : ";
2880   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2881     {
2882       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2883       ret << cm.getRepr() << " ";
2884     }
2885   ret << "\n";
2886   return ret.str();
2887 }
2888
2889 std::string MEDCouplingUMesh::advancedRepr() const
2890 {
2891   std::ostringstream ret;
2892   ret << simpleRepr();
2893   ret << "\nCoordinates array : \n___________________\n\n";
2894   if(_coords)
2895     _coords->reprWithoutNameStream(ret);
2896   else
2897     ret << "No array set !\n";
2898   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2899   reprConnectivityOfThisLL(ret);
2900   return ret.str();
2901 }
2902
2903 /*!
2904  * This method returns a C++ code that is a dump of \a this.
2905  * This method will throw if this is not fully defined.
2906  */
2907 std::string MEDCouplingUMesh::cppRepr() const
2908 {
2909   static const char coordsName[]="coords";
2910   static const char connName[]="conn";
2911   static const char connIName[]="connI";
2912   checkFullyDefined();
2913   std::ostringstream ret; ret << "// coordinates" << std::endl;
2914   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2915   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2916   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2917   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2918   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2919   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2920   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2921   return ret.str();
2922 }
2923
2924 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2925 {
2926   std::ostringstream ret;
2927   reprConnectivityOfThisLL(ret);
2928   return ret.str();
2929 }
2930
2931 /*!
2932  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsibility to deal with.
2933  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2934  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2935  * some algos).
2936  * 
2937  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2938  * 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
2939  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2940  */
2941 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2942 {
2943   int mdim=getMeshDimension();
2944   if(mdim<0)
2945     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2946   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2947   MCAuto<DataArrayInt> tmp1,tmp2;
2948   bool needToCpyCT=true;
2949   if(!_nodal_connec)
2950     {
2951       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2952       needToCpyCT=false;
2953     }
2954   else
2955     {
2956       tmp1=_nodal_connec;
2957       tmp1->incrRef();
2958     }
2959   if(!_nodal_connec_index)
2960     {
2961       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2962       needToCpyCT=false;
2963     }
2964   else
2965     {
2966       tmp2=_nodal_connec_index;
2967       tmp2->incrRef();
2968     }
2969   ret->setConnectivity(tmp1,tmp2,false);
2970   if(needToCpyCT)
2971     ret->_types=_types;
2972   if(!_coords)
2973     {
2974       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2975       ret->setCoords(coords);
2976     }
2977   else
2978     ret->setCoords(_coords);
2979   return ret.retn();
2980 }
2981
2982 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2983 {
2984   const int *ptI=_nodal_connec_index->getConstPointer();
2985   const int *pt=_nodal_connec->getConstPointer();
2986   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2987     return ptI[cellId+1]-ptI[cellId]-1;
2988   else
2989     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2990 }
2991
2992 /*!
2993  * Returns types of cells of the specified part of \a this mesh.
2994  * This method avoids computing sub-mesh explicitly to get its types.
2995  *  \param [in] begin - an array of cell ids of interest.
2996  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2997  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2998  *         describing the cell types. 
2999  *  \throw If the coordinates array is not set.
3000  *  \throw If the nodal connectivity of cells is not defined.
3001  *  \sa getAllGeoTypes()
3002  */
3003 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3004 {
3005   checkFullyDefined();
3006   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3007   const int *conn=_nodal_connec->getConstPointer();
3008   const int *connIndex=_nodal_connec_index->getConstPointer();
3009   for(const int *w=begin;w!=end;w++)
3010     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3011   return ret;
3012 }
3013
3014 /*!
3015  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3016  * Optionally updates
3017  * a set of types of cells constituting \a this mesh. 
3018  * This method is for advanced users having prepared their connectivity before. For
3019  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3020  *  \param [in] conn - the nodal connectivity array. 
3021  *  \param [in] connIndex - the nodal connectivity index array.
3022  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3023  *         mesh is updated.
3024  */
3025 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3026 {
3027   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3028   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3029   if(isComputingTypes)
3030     computeTypes();
3031   declareAsNew();
3032 }
3033
3034 /*!
3035  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3036  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3037  */
3038 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy):MEDCouplingPointSet(other,deepCpy),_mesh_dim(other._mesh_dim),
3039     _nodal_connec(0),_nodal_connec_index(0),
3040     _types(other._types)
3041 {
3042   if(other._nodal_connec)
3043     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCpy);
3044   if(other._nodal_connec_index)
3045     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCpy);
3046 }
3047
3048 MEDCouplingUMesh::~MEDCouplingUMesh()
3049 {
3050   if(_nodal_connec)
3051     _nodal_connec->decrRef();
3052   if(_nodal_connec_index)
3053     _nodal_connec_index->decrRef();
3054 }
3055
3056 /*!
3057  * Recomputes a set of cell types of \a this mesh. For more info see
3058  * \ref MEDCouplingUMeshNodalConnectivity.
3059  */
3060 void MEDCouplingUMesh::computeTypes()
3061 {
3062   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3063 }
3064
3065
3066 /*!
3067  * Returns a number of cells constituting \a this mesh. 
3068  *  \return int - the number of cells in \a this mesh.
3069  *  \throw If the nodal connectivity of cells is not defined.
3070  */
3071 std::size_t MEDCouplingUMesh::getNumberOfCells() const
3072
3073   if(_nodal_connec_index)
3074     return _nodal_connec_index->getNumberOfTuples()-1;
3075   else
3076     if(_mesh_dim==-1)
3077       return 1;
3078     else
3079       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3080 }
3081
3082 /*!
3083  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3084  * mesh. For more info see \ref meshes.
3085  *  \return int - the dimension of \a this mesh.
3086  *  \throw If the mesh dimension is not defined using setMeshDimension().
3087  */
3088 int MEDCouplingUMesh::getMeshDimension() const
3089 {
3090   if(_mesh_dim<-1)
3091     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3092   return _mesh_dim;
3093 }
3094
3095 /*!
3096  * Returns a length of the nodal connectivity array.
3097  * This method is for test reason. Normally the integer returned is not useable by
3098  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3099  *  \return int - the length of the nodal connectivity array.
3100  */
3101 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3102 {
3103   return _nodal_connec->getNbOfElems();
3104 }
3105
3106 /*!
3107  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3108  */
3109 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3110 {
3111   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3112   tinyInfo.push_back(getMeshDimension());
3113   tinyInfo.push_back(getNumberOfCells());
3114   if(_nodal_connec)
3115     tinyInfo.push_back(getNodalConnectivityArrayLen());
3116   else
3117     tinyInfo.push_back(-1);
3118 }
3119
3120 /*!
3121  * First step of unserialization process.
3122  */
3123 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3124 {
3125   return tinyInfo[6]<=0;
3126 }
3127
3128 /*!
3129  * Second step of serialization process.
3130  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3131  * \param a1
3132  * \param a2
3133  * \param littleStrings
3134  */
3135 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3136 {
3137   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3138   if(tinyInfo[5]!=-1)
3139     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3140 }
3141
3142 /*!
3143  * Third and final step of serialization process.
3144  */
3145 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3146 {
3147   MEDCouplingPointSet::serialize(a1,a2);
3148   if(getMeshDimension()>-1)
3149     {
3150       a1=DataArrayInt::New();
3151       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3152       int *ptA1=a1->getPointer();
3153       const int *conn=getNodalConnectivity()->getConstPointer();
3154       const int *index=getNodalConnectivityIndex()->getConstPointer();
3155       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3156       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3157     }
3158   else
3159     a1=0;
3160 }
3161
3162 /*!
3163  * Second and final unserialization process.
3164  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3165  */
3166 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3167 {
3168   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3169   setMeshDimension(tinyInfo[5]);
3170   if(tinyInfo[7]!=-1)
3171     {
3172       // Connectivity
3173       const int *recvBuffer=a1->getConstPointer();
3174       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3175       myConnecIndex->alloc(tinyInfo[6]+1,1);
3176       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3177       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3178       myConnec->alloc(tinyInfo[7],1);
3179       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3180       setConnectivity(myConnec, myConnecIndex);
3181     }
3182 }
3183
3184
3185
3186 /*!
3187  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3188  * mesh.<br>
3189  * For 1D cells, the returned field contains lengths.<br>
3190  * For 2D cells, the returned field contains areas.<br>
3191  * For 3D cells, the returned field contains volumes.
3192  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3193  *         orientation, i.e. the volume is always positive.
3194  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3195  *         and one time . The caller is to delete this field using decrRef() as it is no
3196  *         more needed.
3197  */
3198 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3199 {
3200   std::string name="MeasureOfMesh_";
3201   name+=getName();
3202   int nbelem=getNumberOfCells();
3203   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3204   field->setName(name);
3205   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3206   array->alloc(nbelem,1);
3207   double *area_vol=array->getPointer();
3208   field->setArray(array) ; array=0;
3209   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3210   field->synchronizeTimeWithMesh();
3211   if(getMeshDimension()!=-1)
3212     {
3213       int ipt;
3214       INTERP_KERNEL::NormalizedCellType type;
3215       int dim_space=getSpaceDimension();
3216       const double *coords=getCoords()->getConstPointer();
3217       const int *connec=getNodalConnectivity()->getConstPointer();
3218       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3219       for(int iel=0;iel<nbelem;iel++)
3220         {
3221           ipt=connec_index[iel];
3222           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3223           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);
3224         }
3225       if(isAbs)
3226         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3227     }
3228   else
3229     {
3230       area_vol[0]=std::numeric_limits<double>::max();
3231     }
3232   return field.retn();
3233 }
3234
3235 /*!
3236  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3237  * mesh.<br>
3238  * For 1D cells, the returned array contains lengths.<br>
3239  * For 2D cells, the returned array contains areas.<br>
3240  * For 3D cells, the returned array contains volumes.
3241  * This method avoids building explicitly a part of \a this mesh to perform the work.
3242  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3243  *         orientation, i.e. the volume is always positive.
3244  *  \param [in] begin - an array of cell ids of interest.
3245  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3246  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3247  *          delete this array using decrRef() as it is no more needed.
3248  * 
3249  *  \if ENABLE_EXAMPLES
3250  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3251  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3252  *  \endif
3253  *  \sa getMeasureField()
3254  */
3255 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3256 {
3257   std::string name="PartMeasureOfMesh_";
3258   name+=getName();
3259   int nbelem=(int)std::distance(begin,end);
3260   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3261   array->setName(name);
3262   array->alloc(nbelem,1);
3263   double *area_vol=array->getPointer();
3264   if(getMeshDimension()!=-1)
3265     {
3266       int ipt;
3267       INTERP_KERNEL::NormalizedCellType type;
3268       int dim_space=getSpaceDimension();
3269       const double *coords=getCoords()->getConstPointer();
3270       const int *connec=getNodalConnectivity()->getConstPointer();
3271       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3272       for(const int *iel=begin;iel!=end;iel++)
3273         {
3274           ipt=connec_index[*iel];
3275           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3276           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3277         }
3278       if(isAbs)
3279         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3280     }
3281   else
3282     {
3283       area_vol[0]=std::numeric_limits<double>::max();
3284     }
3285   return array.retn();
3286 }
3287
3288 /*!
3289  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3290  * \a this one. The returned field contains the dual cell volume for each corresponding
3291  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3292  *  the dual mesh in P1 sens of \a this.<br>
3293  * For 1D cells, the returned field contains lengths.<br>
3294  * For 2D cells, the returned field contains areas.<br>
3295  * For 3D cells, the returned field contains volumes.
3296  * This method is useful to check "P1*" conservative interpolators.
3297  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3298  *         orientation, i.e. the volume is always positive.
3299  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3300  *          nodes and one time. The caller is to delete this array using decrRef() as
3301  *          it is no more needed.
3302  */
3303 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3304 {
3305   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3306   std::string name="MeasureOnNodeOfMesh_";
3307   name+=getName();
3308   int nbNodes=getNumberOfNodes();
3309   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3310   double cst=1./((double)getMeshDimension()+1.);
3311   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3312   array->alloc(nbNodes,1);
3313   double *valsToFill=array->getPointer();
3314   std::fill(valsToFill,valsToFill+nbNodes,0.);
3315   const double *values=tmp->getArray()->getConstPointer();
3316   MCAuto<DataArrayInt> da=DataArrayInt::New();
3317   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3318   getReverseNodalConnectivity(da,daInd);
3319   const int *daPtr=da->getConstPointer();
3320   const int *daIPtr=daInd->getConstPointer();
3321   for(int i=0;i<nbNodes;i++)
3322     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3323       valsToFill[i]+=cst*values[*cell];
3324   ret->setMesh(this);
3325   ret->setArray(array);
3326   return ret.retn();
3327 }
3328
3329 /*!
3330  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3331  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3332  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3333  * and are normalized.
3334  * <br> \a this can be either 
3335  * - a  2D mesh in 2D or 3D space or 
3336  * - an 1D mesh in 2D space.
3337  * 
3338  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3339  *          cells and one time. The caller is to delete this field using decrRef() as
3340  *          it is no more needed.
3341  *  \throw If the nodal connectivity of cells is not defined.
3342  *  \throw If the coordinates array is not set.
3343  *  \throw If the mesh dimension is not set.
3344  *  \throw If the mesh and space dimension is not as specified above.
3345  */
3346 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3347 {
3348   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3349     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3350   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3351   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3352   int nbOfCells=getNumberOfCells();
3353   int nbComp=getMeshDimension()+1;
3354   array->alloc(nbOfCells,nbComp);
3355   double *vals=array->getPointer();
3356   const int *connI=_nodal_connec_index->getConstPointer();
3357   const int *conn=_nodal_connec->getConstPointer();
3358   const double *coords=_coords->getConstPointer();
3359   if(getMeshDimension()==2)
3360     {
3361       if(getSpaceDimension()==3)
3362         {
3363           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3364           const double *locPtr=loc->getConstPointer();
3365           for(int i=0;i<nbOfCells;i++,vals+=3)
3366             {
3367               int offset=connI[i];
3368               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3369               double n=INTERP_KERNEL::norm<3>(vals);
3370               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3371             }
3372         }
3373       else
3374         {
3375           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3376           const double *isAbsPtr=isAbs->getArray()->begin();
3377           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3378             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3379         }
3380     }
3381   else//meshdimension==1
3382     {
3383       double tmp[2];
3384       for(int i=0;i<nbOfCells;i++)
3385         {
3386           int offset=connI[i];
3387           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3388           double n=INTERP_KERNEL::norm<2>(tmp);
3389           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3390           *vals++=-tmp[1];
3391           *vals++=tmp[0];
3392         }
3393     }
3394   ret->setArray(array);
3395   ret->setMesh(this);
3396   ret->synchronizeTimeWithSupport();
3397   return ret.retn();
3398 }
3399
3400 /*!
3401  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3402  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3403  * and are normalized.
3404  * <br> \a this can be either 
3405  * - a  2D mesh in 2D or 3D space or 
3406  * - an 1D mesh in 2D space.
3407  * 
3408  * This method avoids building explicitly a part of \a this mesh to perform the work.
3409  *  \param [in] begin - an array of cell ids of interest.
3410  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3411  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3412  *          cells and one time. The caller is to delete this field using decrRef() as
3413  *          it is no more needed.
3414  *  \throw If the nodal connectivity of cells is not defined.
3415  *  \throw If the coordinates array is not set.
3416  *  \throw If the mesh dimension is not set.
3417  *  \throw If the mesh and space dimension is not as specified above.
3418  *  \sa buildOrthogonalField()
3419  *
3420  *  \if ENABLE_EXAMPLES
3421  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3422  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3423  *  \endif
3424  */
3425 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3426 {
3427   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3428     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3429   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3430   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3431   std::size_t nbelems=std::distance(begin,end);
3432   int nbComp=getMeshDimension()+1;
3433   array->alloc((int)nbelems,nbComp);
3434   double *vals=array->getPointer();
3435   const int *connI=_nodal_connec_index->getConstPointer();
3436   const int *conn=_nodal_connec->getConstPointer();
3437   const double *coords=_coords->getConstPointer();
3438   if(getMeshDimension()==2)
3439     {
3440       if(getSpaceDimension()==3)
3441         {
3442           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3443           const double *locPtr=loc->getConstPointer();
3444           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3445             {
3446               int offset=connI[*i];
3447               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3448               double n=INTERP_KERNEL::norm<3>(vals);
3449               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3450             }
3451         }
3452       else
3453         {
3454           for(std::size_t i=0;i<nbelems;i++)
3455             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3456         }
3457     }
3458   else//meshdimension==1
3459     {
3460       double tmp[2];
3461       for(const int *i=begin;i!=end;i++)
3462         {
3463           int offset=connI[*i];
3464           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3465           double n=INTERP_KERNEL::norm<2>(tmp);
3466           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3467           *vals++=-tmp[1];
3468           *vals++=tmp[0];
3469         }
3470     }
3471   ret->setArray(array);
3472   ret->setMesh(this);
3473   ret->synchronizeTimeWithSupport();
3474   return ret.retn();
3475 }
3476
3477 /*!
3478  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3479  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3480  * and are \b not normalized.
3481  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3482  *          cells and one time. The caller is to delete this field using decrRef() as
3483  *          it is no more needed.
3484  *  \throw If the nodal connectivity of cells is not defined.
3485  *  \throw If the coordinates array is not set.
3486  *  \throw If \a this->getMeshDimension() != 1.
3487  *  \throw If \a this mesh includes cells of type other than SEG2.
3488  */
3489 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3490 {
3491   if(getMeshDimension()!=1)
3492     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3493   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3494     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3495   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3496   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3497   int nbOfCells=getNumberOfCells();
3498   int spaceDim=getSpaceDimension();
3499   array->alloc(nbOfCells,spaceDim);
3500   double *pt=array->getPointer();
3501   const double *coo=getCoords()->getConstPointer();
3502   std::vector<int> conn;
3503   conn.reserve(2);
3504   for(int i=0;i<nbOfCells;i++)
3505     {
3506       conn.resize(0);
3507       getNodeIdsOfCell(i,conn);
3508       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3509     }
3510   ret->setArray(array);
3511   ret->setMesh(this);
3512   ret->synchronizeTimeWithSupport();
3513   return ret.retn();
3514 }
3515
3516 /*!
3517  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3518  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3519  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3520  * from. If a result face is shared by two 3D cells, then the face in included twice in
3521  * the result mesh.
3522  *  \param [in] origin - 3 components of a point defining location of the plane.
3523  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3524  *         must be greater than 1e-6.
3525  *  \param [in] eps - half-thickness of the plane.
3526  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3527  *         producing correspondent 2D cells. The caller is to delete this array
3528  *         using decrRef() as it is no more needed.
3529  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3530  *         not share the node coordinates array with \a this mesh. The caller is to
3531  *         delete this mesh using decrRef() as it is no more needed.  
3532  *  \throw If the coordinates array is not set.
3533  *  \throw If the nodal connectivity of cells is not defined.
3534  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3535  *  \throw If magnitude of \a vec is less than 1e-6.
3536  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3537  *  \throw If \a this includes quadratic cells.
3538  */
3539 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3540 {
3541   checkFullyDefined();
3542   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3543     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3544   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3545   if(candidates->empty())
3546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3547   std::vector<int> nodes;
3548   DataArrayInt *cellIds1D=0;
3549   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3550   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3551   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3552   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3553   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3554   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3555   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3556   revDesc2=0; revDescIndx2=0;
3557   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3558   revDesc1=0; revDescIndx1=0;
3559   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3560   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3561   //
3562   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3563   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3564     cut3DCurve[*it]=-1;
3565   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3566   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3567   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3568                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3569                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3570   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3571   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3572   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3573   if(cellIds2->empty())
3574     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3575   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3576   ret->setCoords(mDesc1->getCoords());
3577   ret->setConnectivity(conn,connI,true);
3578   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3579   return ret.retn();
3580 }
3581
3582 /*!
3583  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3584 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
3585 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3586 the result mesh.
3587  *  \param [in] origin - 3 components of a point defining location of the plane.
3588  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3589  *         must be greater than 1e-6.
3590  *  \param [in] eps - half-thickness of the plane.
3591  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3592  *         producing correspondent segments. The caller is to delete this array
3593  *         using decrRef() as it is no more needed.
3594  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3595  *         mesh in 3D space. This mesh does not share the node coordinates array with
3596  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3597  *         no more needed. 
3598  *  \throw If the coordinates array is not set.
3599  *  \throw If the nodal connectivity of cells is not defined.
3600  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3601  *  \throw If magnitude of \a vec is less than 1e-6.
3602  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3603  *  \throw If \a this includes quadratic cells.
3604  */
3605 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3606 {
3607   checkFullyDefined();
3608   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3610   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3611   if(candidates->empty())
3612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3613   std::vector<int> nodes;
3614   DataArrayInt *cellIds1D(0);
3615   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3616   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3617   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3618   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3619   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3620   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3621   //
3622   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3623   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3624     cut3DCurve[*it]=-1;
3625   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3626   int ncellsSub=subMesh->getNumberOfCells();
3627   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3628   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3629                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3630                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3631   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3632   conn->alloc(0,1);
3633   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3634   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3635   for(int i=0;i<ncellsSub;i++)
3636     {
3637       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3638         {
3639           if(cut3DSurf[i].first!=-2)
3640             {
3641               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3642               connI->pushBackSilent(conn->getNumberOfTuples());
3643               cellIds2->pushBackSilent(i);
3644             }
3645           else
3646             {
3647               int cellId3DSurf=cut3DSurf[i].second;
3648               int offset=nodalI[cellId3DSurf]+1;
3649               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3650               for(int j=0;j<nbOfEdges;j++)
3651                 {
3652                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3653                   connI->pushBackSilent(conn->getNumberOfTuples());
3654                   cellIds2->pushBackSilent(cellId3DSurf);
3655                 }
3656             }
3657         }
3658     }
3659   if(cellIds2->empty())
3660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3661   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3662   ret->setCoords(mDesc1->getCoords());
3663   ret->setConnectivity(conn,connI,true);
3664   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3665   return ret.retn();
3666 }
3667
3668 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3669 {
3670   checkFullyDefined();
3671   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3672     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3673   if(getNumberOfCells()!=1)
3674     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3675   //
3676   std::vector<int> nodes;
3677   findNodesOnPlane(origin,vec,eps,nodes);
3678   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc2(DataArrayInt::New()),descIndx1(DataArrayInt::New()),descIndx2(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDesc2(DataArrayInt::New()),revDescIndx1(DataArrayInt::New()),revDescIndx2(DataArrayInt::New());
3679   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3680   revDesc2=0; revDescIndx2=0;
3681   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3682   revDesc1=0; revDescIndx1=0;
3683   DataArrayInt *cellIds1D(0);
3684   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3685   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3686   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3687   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3688     cut3DCurve[*it]=-1;
3689   bool sameNbNodes;
3690   {
3691     int oldNbNodes(mDesc1->getNumberOfNodes());
3692     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3693     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3694   }
3695   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3696   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3697                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3698                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3699   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3700   connI->pushBackSilent(0); conn->alloc(0,1);
3701   {
3702     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3703     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3704     if(cellIds2->empty())
3705       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3706   }
3707   std::vector<std::vector<int> > res;
3708   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3709   std::size_t sz(res.size());
3710   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3712   for(std::size_t i=0;i<sz;i++)
3713     {
3714       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3715       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3716       connI->pushBackSilent(conn->getNumberOfTuples());
3717     }
3718   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3719   ret->setCoords(mDesc1->getCoords());
3720   ret->setConnectivity(conn,connI,true);
3721   int nbCellsRet(ret->getNumberOfCells());
3722   //
3723   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3724   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3725   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3726   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3727   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3728   MCAuto<DataArrayDouble> occm;
3729   {
3730     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3731     occm=DataArrayDouble::Substract(ccm,pt);
3732   }
3733   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3734   vec2->setPartOfValuesSimple1(vec[0],0,nbCellsRet,1,0,1,1); vec2->setPartOfValuesSimple1(vec[1],0,nbCellsRet,1,1,2,1); vec2->setPartOfValuesSimple1(vec[2],0,nbCellsRet,1,2,3,1);
3735   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3736   //
3737   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3738   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3739   ret2->setCoords(mDesc1->getCoords());
3740   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3741   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3742   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3743   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3744   if(dott->getIJ(0,0)>0)
3745     {
3746       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3747       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3748     }
3749   else
3750     {
3751       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3752       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3753     }
3754   for(int i=1;i<nbCellsRet;i++)
3755     {
3756       if(dott2->getIJ(i,0)<0)
3757         {
3758           if(ciPtr[i+1]-ciPtr[i]>=4)
3759             {
3760               cell0.push_back(-1);
3761               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3762             }
3763         }
3764       else
3765         {
3766           if(ciPtr[i+1]-ciPtr[i]>=4)
3767             {
3768               cell1.push_back(-1);
3769               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3770             }
3771         }
3772     }
3773   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3774   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3775   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3776   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3777   ret2->setConnectivity(conn2,conn2I,true);
3778   ret2->checkConsistencyLight();
3779   ret2->orientCorrectlyPolyhedrons();
3780   return ret2;
3781 }
3782
3783 /*!
3784  * Finds cells whose bounding boxes intersect a given plane.
3785  *  \param [in] origin - 3 components of a point defining location of the plane.
3786  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3787  *         must be greater than 1e-6.
3788  *  \param [in] eps - half-thickness of the plane.
3789  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3790  *         cells. The caller is to delete this array using decrRef() as it is no more
3791  *         needed.
3792  *  \throw If the coordinates array is not set.
3793  *  \throw If the nodal connectivity of cells is not defined.
3794  *  \throw If \a this->getSpaceDimension() != 3.
3795  *  \throw If magnitude of \a vec is less than 1e-6.
3796  *  \sa buildSlice3D()
3797  */
3798 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3799 {
3800   checkFullyDefined();
3801   if(getSpaceDimension()!=3)
3802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3803   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3804   if(normm<1e-6)
3805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3806   double vec2[3];
3807   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3808   double angle=acos(vec[2]/normm);
3809   MCAuto<DataArrayInt> cellIds;
3810   double bbox[6];
3811   if(angle>eps)
3812     {
3813       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3814       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3815       if(normm2/normm>1e-6)
3816         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3817       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3818       mw->setCoords(coo);
3819       mw->getBoundingBox(bbox);
3820       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3821       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3822     }
3823   else
3824     {
3825       getBoundingBox(bbox);
3826       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3827       cellIds=getCellsInBoundingBox(bbox,eps);
3828     }
3829   return cellIds.retn();
3830 }
3831
3832 /*!
3833  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3834  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3835  * No consideration of coordinate is done by this method.
3836  * 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)
3837  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be useful.
3838  */
3839 bool MEDCouplingUMesh::isContiguous1D() const
3840 {
3841   if(getMeshDimension()!=1)
3842     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3843   int nbCells=getNumberOfCells();
3844   if(nbCells<1)
3845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3846   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3847   int ref=conn[connI[0]+2];
3848   for(int i=1;i<nbCells;i++)
3849     {
3850       if(conn[connI[i]+1]!=ref)
3851         return false;
3852       ref=conn[connI[i]+2];
3853     }
3854   return true;
3855 }
3856
3857 /*!
3858  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3859  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3860  * \param pt reference point of the line
3861  * \param v normalized director vector of the line
3862  * \param eps max precision before throwing an exception
3863  * \param res output of size this->getNumberOfCells
3864  */
3865 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3866 {
3867   if(getMeshDimension()!=1)
3868     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3869   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3870     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3871   if(getSpaceDimension()!=3)
3872     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3873   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3874   const double *fPtr=f->getArray()->getConstPointer();
3875   double tmp[3];
3876   for(std::size_t i=0;i<getNumberOfCells();i++)
3877     {
3878       const double *tmp1=fPtr+3*i;
3879       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3880       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3881       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3882       double n1=INTERP_KERNEL::norm<3>(tmp);
3883       n1/=INTERP_KERNEL::norm<3>(tmp1);
3884       if(n1>eps)
3885         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3886     }
3887   const double *coo=getCoords()->getConstPointer();
3888   for(int i=0;i<getNumberOfNodes();i++)
3889     {
3890       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3891       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3892       res[i]=std::accumulate(tmp,tmp+3,0.);
3893     }
3894 }
3895
3896 /*!
3897  * 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. 
3898  * \a this is expected to be a mesh so that its space dimension is equal to its
3899  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3900  * 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).
3901  *
3902  * 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
3903  * 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).
3904  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3905  *
3906  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3907  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3908  *
3909  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3910  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3911  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3912  * \return the positive value of the distance.
3913  * \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
3914  * dimension - 1.
3915  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3916  */
3917 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3918 {
3919   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3920   if(meshDim!=spaceDim-1)
3921     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3922   if(meshDim!=2 && meshDim!=1)
3923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3924   checkFullyDefined();
3925   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3926     { 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()); }
3927   DataArrayInt *ret1=0;
3928   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3929   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3930   MCAuto<DataArrayInt> ret1Safe(ret1);
3931   cellId=*ret1Safe->begin();
3932   return *ret0->begin();
3933 }
3934
3935 /*!
3936  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3937  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3938  * 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
3939  * 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).
3940  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3941  * 
3942  * \a this is expected to be a mesh so that its space dimension is equal to its
3943  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3944  * 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).
3945  *
3946  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3947  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3948  *
3949  * \param [in] pts the list of points in which each tuple represents a point
3950  * \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.
3951  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3952  * \throw if number of components of \a pts is not equal to the space dimension.
3953  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3954  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3955  */
3956 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3957 {
3958   if(!pts)
3959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3960   pts->checkAllocated();
3961   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3962   if(meshDim!=spaceDim-1)
3963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3964   if(meshDim!=2 && meshDim!=1)
3965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3966   if((int)pts->getNumberOfComponents()!=spaceDim)
3967     {
3968       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3969       throw INTERP_KERNEL::Exception(oss.str());
3970     }
3971   checkFullyDefined();
3972   int nbCells=getNumberOfCells();
3973   if(nbCells==0)
3974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3975   int nbOfPts=pts->getNumberOfTuples();
3976   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3977   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3978   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3979   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3980   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3981   const double *bbox(bboxArr->begin());
3982   switch(spaceDim)
3983   {
3984     case 3:
3985       {
3986         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3987         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3988           {
3989             double x=std::numeric_limits<double>::max();
3990             std::vector<int> elems;
3991             myTree.getMinDistanceOfMax(ptsPtr,x);
3992             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3993             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3994           }
3995         break;
3996       }
3997     case 2:
3998       {
3999         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4000         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4001           {
4002             double x=std::numeric_limits<double>::max();
4003             std::vector<int> elems;
4004             myTree.getMinDistanceOfMax(ptsPtr,x);
4005             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4006             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4007           }
4008         break;
4009       }
4010     default:
4011       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4012   }
4013   cellIds=ret1.retn();
4014   return ret0.retn();
4015 }
4016
4017 /// @cond INTERNAL
4018
4019 /// @endcond
4020
4021 /*!
4022  * Finds cells in contact with a ball (i.e. a point with precision). 
4023  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4024  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4025  *
4026  * \warning This method is suitable if the caller intends to evaluate only one
4027  *          point, for more points getCellsContainingPoints() is recommended as it is
4028  *          faster. 
4029  *  \param [in] pos - array of coordinates of the ball central point.
4030  *  \param [in] eps - ball radius.
4031  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4032  *         if there are no such cells.
4033  *  \throw If the coordinates array is not set.
4034  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4035  */
4036 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4037 {
4038   std::vector<int> elts;
4039   getCellsContainingPoint(pos,eps,elts);
4040   if(elts.empty())
4041     return -1;
4042   return elts.front();
4043 }
4044
4045 /*!
4046  * Finds cells in contact with a ball (i.e. a point with precision).
4047  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4048  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4049  * \warning This method is suitable if the caller intends to evaluate only one
4050  *          point, for more points getCellsContainingPoints() is recommended as it is
4051  *          faster. 
4052  *  \param [in] pos - array of coordinates of the ball central point.
4053  *  \param [in] eps - ball radius.
4054  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4055  *         before inserting ids.
4056  *  \throw If the coordinates array is not set.
4057  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4058  *
4059  *  \if ENABLE_EXAMPLES
4060  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4061  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4062  *  \endif
4063  */
4064 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4065 {
4066   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4067   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4068   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4069 }
4070
4071 void MEDCouplingUMesh::getCellsContainingPointsZeAlg(const double *pos, int nbOfPoints, double eps,
4072                                                      MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex,
4073                                                      std::function<bool(INTERP_KERNEL::NormalizedCellType,int)> sensibilityTo2DQuadraticLinearCellsFunc) const
4074 {
4075   int spaceDim(getSpaceDimension()),mDim(getMeshDimension());
4076   if(spaceDim==3)
4077     {
4078       if(mDim==3)
4079         {
4080           const double *coords=_coords->getConstPointer();
4081           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4082         }
4083       else
4084         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4085     }
4086   else if(spaceDim==2)
4087     {
4088       if(mDim==2)
4089         {
4090           const double *coords=_coords->getConstPointer();
4091           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4092         }
4093       else
4094         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4095     }
4096   else if(spaceDim==1)
4097     {
4098       if(mDim==1)
4099         {
4100           const double *coords=_coords->getConstPointer();
4101           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4102         }
4103       else
4104         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4105     }
4106   else
4107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4108 }
4109
4110 /*!
4111  * Finds cells in contact with several balls (i.e. points with precision).
4112  * This method is an extension of getCellContainingPoint() and
4113  * getCellsContainingPoint() for the case of multiple points.
4114  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4115  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4116  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4117  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4118  *         this->getSpaceDimension() * \a nbOfPoints 
4119  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4120  *  \param [in] eps - radius of balls (i.e. the precision).
4121  *  \param [out] elts - vector returning ids of found cells.
4122  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4123  *         dividing cell ids in \a elts into groups each referring to one
4124  *         point. Its every element (except the last one) is an index pointing to the
4125  *         first id of a group of cells. For example cells in contact with the *i*-th
4126  *         point are described by following range of indices:
4127  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4128  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4129  *         Number of cells in contact with the *i*-th point is
4130  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4131  *  \throw If the coordinates array is not set.
4132  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4133  *
4134  *  \if ENABLE_EXAMPLES
4135  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4136  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4137  *  \endif
4138  */
4139 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4140                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4141 {
4142   auto yesImSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType ct, int mdim) { return INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic() && mdim == 2; } );
4143   this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,yesImSensibleTo2DQuadraticLinearCellsFunc);
4144 }
4145
4146 /*!
4147  * Behaves like MEDCouplingMesh::getCellsContainingPoints for cells in \a this that are linear.
4148  * For quadratic cells in \a this, this method behaves by just considering linear part of cells.
4149  * This method is here only for backward compatibility (interpolation GaussPoints to GaussPoints).
4150  * 
4151  * \sa MEDCouplingUMesh::getCellsContainingPoints, MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss
4152  */
4153 void MEDCouplingUMesh::getCellsContainingPointsLinearPartOnlyOnNonDynType(const double *pos, int nbOfPoints, double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4154 {
4155   auto noImNotSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType,int) { return false; } );
4156   this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,noImNotSensibleTo2DQuadraticLinearCellsFunc);
4157 }
4158
4159 /*!
4160  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4161  * least two its edges intersect each other anywhere except their extremities. An
4162  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4163  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4164  *         cleared before filling in.
4165  *  \param [in] eps - precision.
4166  *  \throw If \a this->getMeshDimension() != 2.
4167  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4168  */
4169 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4170 {
4171   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4172   if(getMeshDimension()!=2)
4173     throw INTERP_KERNEL::Exception(msg);
4174   int spaceDim=getSpaceDimension();
4175   if(spaceDim!=2 && spaceDim!=3)
4176     throw INTERP_KERNEL::Exception(msg);
4177   const int *conn=_nodal_connec->getConstPointer();
4178   const int *connI=_nodal_connec_index->getConstPointer();
4179   int nbOfCells=getNumberOfCells();
4180   std::vector<double> cell2DinS2;
4181   for(int i=0;i<nbOfCells;i++)
4182     {
4183       int offset=connI[i];
4184       int nbOfNodesForCell=connI[i+1]-offset-1;
4185       if(nbOfNodesForCell<=3)
4186         continue;
4187       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4188       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4189       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4190         cells.push_back(i);
4191       cell2DinS2.clear();
4192     }
4193 }
4194
4195 /*!
4196  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4197  *
4198  * 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.
4199  * 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.
4200  * 
4201  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4202  * This convex envelop is computed using Jarvis march algorithm.
4203  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4204  * 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)
4205  * 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.
4206  *
4207  * \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.
4208  * \sa MEDCouplingUMesh::colinearize2D
4209  */
4210 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4211 {
4212   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4213     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4214   checkFullyDefined();
4215   const double *coords=getCoords()->getConstPointer();
4216   int nbOfCells=getNumberOfCells();
4217   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4218   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4219   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4220   int *workIndexOut=nodalConnecIndexOut->getPointer();
4221   *workIndexOut=0;
4222   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4223   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4224   std::set<INTERP_KERNEL::NormalizedCellType> types;
4225   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4226   isChanged->alloc(0,1);
4227   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4228     {
4229       int pos=nodalConnecOut->getNumberOfTuples();
4230       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4231         isChanged->pushBackSilent(i);
4232       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4233       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4234     }
4235   if(isChanged->empty())
4236     return 0;
4237   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4238   _types=types;
4239   return isChanged.retn();
4240 }
4241
4242 /*!
4243  * This method is \b NOT const because it can modify \a this.
4244  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4245  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4246  * \param policy specifies the type of extrusion chosen:
4247  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4248  *   will be repeated to build each level
4249  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4250  *   the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4251  *   along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4252  *   arc.
4253  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4254  */
4255 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4256 {
4257   checkFullyDefined();
4258   mesh1D->checkFullyDefined();
4259   if(!mesh1D->isContiguous1D())
4260     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4261   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4262     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4263   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4264     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4265   if(mesh1D->getMeshDimension()!=1)
4266     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4267   bool isQuad=false;
4268   if(isPresenceOfQuadratic())
4269     {
4270       if(mesh1D->isFullyQuadratic())
4271         isQuad=true;
4272       else
4273         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4274     }
4275   int oldNbOfNodes(getNumberOfNodes());
4276   MCAuto<DataArrayDouble> newCoords;
4277   switch(policy)
4278   {
4279     case 0:
4280       {
4281         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4282         break;
4283       }
4284     case 1:
4285       {
4286         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4287         break;
4288       }
4289     default:
4290       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4291   }
4292   setCoords(newCoords);
4293   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4294   updateTime();
4295   return ret.retn();
4296 }
4297
4298
4299 /*!
4300  * Checks if \a this mesh is constituted by only quadratic cells.
4301  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4302  *  \throw If the coordinates array is not set.
4303  *  \throw If the nodal connectivity of cells is not defined.
4304  */
4305 bool MEDCouplingUMesh::isFullyQuadratic() const
4306 {
4307   checkFullyDefined();
4308   bool ret=true;
4309   int nbOfCells=getNumberOfCells();
4310   for(int i=0;i<nbOfCells && ret;i++)
4311     {
4312       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4313       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4314       ret=cm.isQuadratic();
4315     }
4316   return ret;
4317 }
4318
4319 /*!
4320  * Checks if \a this mesh includes any quadratic cell.
4321  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4322  *  \throw If the coordinates array is not set.
4323  *  \throw If the nodal connectivity of cells is not defined.
4324  */
4325 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4326 {
4327   checkFullyDefined();
4328   bool ret=false;
4329   int nbOfCells=getNumberOfCells();
4330   for(int i=0;i<nbOfCells && !ret;i++)
4331     {
4332       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4333       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4334       ret=cm.isQuadratic();
4335     }
4336   return ret;
4337 }
4338
4339 /*!
4340  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4341  * this mesh, it remains unchanged.
4342  *  \throw If the coordinates array is not set.
4343  *  \throw If the nodal connectivity of cells is not defined.
4344  */
4345 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4346 {
4347   checkFullyDefined();
4348   int nbOfCells(getNumberOfCells());
4349   int delta=0;
4350   const int *iciptr=_nodal_connec_index->begin();
4351   for(int i=0;i<nbOfCells;i++)
4352     {
4353       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4354       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4355       if(cm.isQuadratic())
4356         {
4357           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4358           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4359           if(!cml.isDynamic())
4360             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4361           else
4362             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4363         }
4364     }
4365   if(delta==0)
4366     return ;
4367   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4368   const int *icptr(_nodal_connec->begin());
4369   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4370   newConnI->alloc(nbOfCells+1,1);
4371   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4372   *ociptr=0;
4373   _types.clear();
4374   for(int i=0;i<nbOfCells;i++,ociptr++)
4375     {
4376       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4377       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4378       if(!cm.isQuadratic())
4379         {
4380           _types.insert(type);
4381           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4382           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4383         }
4384       else
4385         {
4386           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4387           _types.insert(typel);
4388           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4389           int newNbOfNodes=cml.getNumberOfNodes();
4390           if(cml.isDynamic())
4391             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4392           *ocptr++=(int)typel;
4393           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4394           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4395         }
4396     }
4397   setConnectivity(newConn,newConnI,false);
4398 }
4399
4400 /*!
4401  * This method converts all linear cell in \a this to quadratic one.
4402  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4403  * 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)
4404  * 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.
4405  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4406  * end of the existing coordinates.
4407  * 
4408  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4409  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4410  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4411  * 
4412  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4413  *
4414  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4415  */
4416 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4417 {
4418   DataArrayInt *conn=0,*connI=0;
4419   DataArrayDouble *coords=0;
4420   std::set<INTERP_KERNEL::NormalizedCellType> types;
4421   checkFullyDefined();
4422   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4423   MCAuto<DataArrayDouble> coordsSafe;
4424   int meshDim=getMeshDimension();
4425   switch(conversionType)
4426   {
4427     case 0:
4428       switch(meshDim)
4429       {
4430         case 1:
4431           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4432           connSafe=conn; connISafe=connI; coordsSafe=coords;
4433           break;
4434         case 2:
4435           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4436           connSafe=conn; connISafe=connI; coordsSafe=coords;
4437           break;
4438         case 3:
4439           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4440           connSafe=conn; connISafe=connI; coordsSafe=coords;
4441           break;
4442         default:
4443           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4444       }
4445       break;
4446         case 1:
4447           {
4448             switch(meshDim)
4449             {
4450               case 1:
4451                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4452                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4453                 break;
4454               case 2:
4455                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4456                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4457                 break;
4458               case 3:
4459                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4460                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4461                 break;
4462               default:
4463                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4464             }
4465             break;
4466           }
4467         default:
4468           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4469   }
4470   setConnectivity(connSafe,connISafe,false);
4471   _types=types;
4472   setCoords(coordsSafe);
4473   return ret.retn();
4474 }
4475
4476 /*!
4477  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4478  * so that the number of cells remains the same. Quadratic faces are converted to
4479  * polygons. This method works only for 2D meshes in
4480  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4481  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4482  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4483  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4484  *         a polylinized edge constituting the input polygon.
4485  *  \throw If the coordinates array is not set.
4486  *  \throw If the nodal connectivity of cells is not defined.
4487  *  \throw If \a this->getMeshDimension() != 2.
4488  *  \throw If \a this->getSpaceDimension() != 2.
4489  */
4490 void MEDCouplingUMesh::tessellate2D(double eps)
4491 {
4492   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4493   if(spaceDim!=2)
4494     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4495   switch(meshDim)
4496     {
4497     case 1:
4498       return tessellate2DCurveInternal(eps);
4499     case 2:
4500       return tessellate2DInternal(eps);
4501     default:
4502       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4503     }
4504 }
4505 /*!
4506  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4507  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4508  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4509  *         a sub-divided edge.
4510  *  \throw If the coordinates array is not set.
4511  *  \throw If the nodal connectivity of cells is not defined.
4512  *  \throw If \a this->getMeshDimension() != 1.
4513  *  \throw If \a this->getSpaceDimension() != 2.
4514  */
4515
4516 #if 0
4517 /*!
4518  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4519  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4520  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4521  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4522  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4523  * This method can be seen as the opposite method of colinearize2D.
4524  * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
4525  * to avoid to modify the numbering of existing nodes.
4526  *
4527  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4528  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4529  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4530  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4531  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4532  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4533  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4534  *
4535  * \sa buildDescendingConnectivity2
4536  */
4537 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4538                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4539 {
4540   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4541     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4542   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4543   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4544     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4545   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4547   //DataArrayInt *out0(0),*outi0(0);
4548   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4549   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4550   //out0s=out0s->buildUnique(); out0s->sort(true);
4551 }
4552 #endif
4553
4554
4555 /*!
4556  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4557  * In addition, returns an array mapping new cells to old ones. <br>
4558  * This method typically increases the number of cells in \a this mesh
4559  * but the number of nodes remains \b unchanged.
4560  * That's why the 3D splitting policies
4561  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4562  *  \param [in] policy - specifies a pattern used for splitting.
4563  * The semantic of \a policy is:
4564  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4565  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4566  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4567  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4568  *
4569  *
4570  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4571  *          an id of old cell producing it. The caller is to delete this array using
4572  *         decrRef() as it is no more needed.
4573  *
4574  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4575  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4576  *          and \a this->getMeshDimension() != 3. 
4577  *  \throw If \a policy is not one of the four discussed above.
4578  *  \throw If the nodal connectivity of cells is not defined.
4579  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4580  */
4581 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4582 {
4583   switch(policy)
4584   {
4585     case 0:
4586       return simplexizePol0();
4587     case 1:
4588       return simplexizePol1();
4589     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4590         return simplexizePlanarFace5();
4591     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4592         return simplexizePlanarFace6();
4593     default:
4594       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)");
4595   }
4596 }
4597
4598 /*!
4599  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4600  * - 1D: INTERP_KERNEL::NORM_SEG2
4601  * - 2D: INTERP_KERNEL::NORM_TRI3
4602  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4603  *
4604  * This method is useful for users that need to use P1 field services as
4605  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4606  * All these methods need mesh support containing only simplex cells.
4607  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4608  *  \throw If the coordinates array is not set.
4609  *  \throw If the nodal connectivity of cells is not defined.
4610  *  \throw If \a this->getMeshDimension() < 1.
4611  */
4612 bool MEDCouplingUMesh::areOnlySimplexCells() const
4613 {
4614   checkFullyDefined();
4615   int mdim=getMeshDimension();
4616   if(mdim<1 || mdim>3)
4617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4618   int nbCells=getNumberOfCells();
4619   const int *conn=_nodal_connec->begin();
4620   const int *connI=_nodal_connec_index->begin();
4621   for(int i=0;i<nbCells;i++)
4622     {
4623       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4624       if(!cm.isSimplex())
4625         return false;
4626     }
4627   return true;
4628 }
4629
4630
4631
4632 /*!
4633  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4634  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4635  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell.
4636  * Quadratic cells in 2D are also handled. In those cells edges where start=end=midpoint are removed.
4637  * This method does \b not perform geometrical checks and checks only nodal connectivity of cells,
4638  * so it can be useful to call mergeNodes() before calling this method.
4639  *  \throw If \a this->getMeshDimension() <= 1.
4640  *  \throw If the coordinates array is not set.
4641  *  \throw If the nodal connectivity of cells is not defined.
4642  */
4643 void MEDCouplingUMesh::convertDegeneratedCells()
4644 {
4645   checkFullyDefined();
4646   if(getMeshDimension()<=1)
4647     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4648   int nbOfCells=getNumberOfCells();
4649   if(nbOfCells<1)
4650     return ;
4651   int initMeshLgth=getNodalConnectivityArrayLen();
4652   int *conn=_nodal_connec->getPointer();
4653   int *index=_nodal_connec_index->getPointer();
4654   int posOfCurCell=0;
4655   int newPos=0;
4656   int lgthOfCurCell;
4657   for(int i=0;i<nbOfCells;i++)
4658     {
4659       lgthOfCurCell=index[i+1]-posOfCurCell;
4660       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4661       int newLgth;
4662       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4663                                                                                                      conn+newPos+1,newLgth);
4664       conn[newPos]=newType;
4665       newPos+=newLgth+1;
4666       posOfCurCell=index[i+1];
4667       index[i+1]=newPos;
4668     }
4669   if(newPos!=initMeshLgth)
4670     _nodal_connec->reAlloc(newPos);
4671   computeTypes();
4672 }
4673
4674 /*!
4675  * Same as MEDCouplingUMesh::convertDegeneratedCells() plus deletion of the flat cells.
4676  * A cell is flat in the following cases:
4677  *   - for a linear cell, all points in the connectivity are equal
4678  *   - for a quadratic cell, either the above, or a quadratic polygon with two (linear) points and two
4679  *   identical quadratic points
4680  * \return a new instance of DataArrayInt holding ids of removed cells. The caller is to delete
4681  *      this array using decrRef() as it is no more needed.
4682  */
4683 DataArrayInt *MEDCouplingUMesh::convertDegeneratedCellsAndRemoveFlatOnes()
4684 {
4685   checkFullyDefined();
4686   if(getMeshDimension()<=1)
4687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4688   int nbOfCells=getNumberOfCells();
4689   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4690   if(nbOfCells<1)
4691     return ret.retn();
4692   int initMeshLgth=getNodalConnectivityArrayLen();
4693   int *conn=_nodal_connec->getPointer();
4694   int *index=_nodal_connec_index->getPointer();
4695   int posOfCurCell=0;
4696   int newPos=0;
4697   int lgthOfCurCell, nbDelCells(0);
4698   for(int i=0;i<nbOfCells;i++)
4699     {
4700       lgthOfCurCell=index[i+1]-posOfCurCell;
4701       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4702       int newLgth;
4703       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4704                                                                                                      conn+newPos+1,newLgth);
4705       // Shall we delete the cell if it is completely degenerated:
4706       bool delCell=INTERP_KERNEL::CellSimplify::isFlatCell(conn, newPos, newLgth, newType);
4707       if (delCell)
4708         {
4709           nbDelCells++;
4710           ret->pushBackSilent(i);
4711         }
4712       else   //if the cell is to be deleted, simply stay at the same place
4713         {
4714           conn[newPos]=newType;
4715           newPos+=newLgth+1;
4716         }
4717       posOfCurCell=index[i+1];
4718       index[i+1-nbDelCells]=newPos;
4719     }
4720   if(newPos!=initMeshLgth)
4721     _nodal_connec->reAlloc(newPos);
4722   const int nCellDel=ret->getNumberOfTuples();
4723   if (nCellDel)
4724     _nodal_connec_index->reAlloc(nbOfCells-nCellDel+1);
4725   computeTypes();
4726   return ret.retn();
4727 }
4728
4729 /*!
4730  * This method remove null 1D cells from \a this. A 1D cell is considered null if start node is equal to end node.
4731  * Only connectivity is considered here.
4732  */
4733 bool MEDCouplingUMesh::removeDegenerated1DCells()
4734 {
4735   checkConnectivityFullyDefined();
4736   if(getMeshDimension()!=1)
4737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::removeDegenerated1DCells works on umeshes with meshdim equals to 1 !");
4738   std::size_t nbCells(getNumberOfCells()),newSize(0),newSize2(0);
4739   const int *conn(getNodalConnectivity()->begin()),*conni(getNodalConnectivityIndex()->begin());
4740   {
4741     for(std::size_t i=0;i<nbCells;i++)
4742       {
4743         INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[conni[i]]);
4744         if(ct==INTERP_KERNEL::NORM_SEG2 || ct==INTERP_KERNEL::NORM_SEG3)
4745           {
4746             if(conn[conni[i]+1]!=conn[conni[i]+2])
4747               {
4748                 newSize++;
4749                 newSize2+=conni[i+1]-conni[i];
4750               }
4751           }
4752         else
4753           {
4754             std::ostringstream oss; oss << "MEDCouplingUMesh::removeDegenerated1DCells : cell #" << i << " in this is not of type SEG2/SEG3 !";
4755             throw INTERP_KERNEL::Exception(oss.str());
4756           }
4757       }
4758   }
4759   if(newSize==nbCells)//no cells has been removed -> do nothing
4760     return false;
4761   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New()); newConnI->alloc(newSize+1,1); newConn->alloc(newSize2,1);
4762   int *newConnPtr(newConn->getPointer()),*newConnIPtr(newConnI->getPointer()); newConnIPtr[0]=0;
4763   for(std::size_t i=0;i<nbCells;i++)
4764     {
4765       if(conn[conni[i]+1]!=conn[conni[i]+2])
4766         {
4767           newConnIPtr[1]=newConnIPtr[0]+conni[i+1]-conni[i];
4768           newConnPtr=std::copy(conn+conni[i],conn+conni[i+1],newConnPtr);
4769           newConnIPtr++;
4770         }
4771     }
4772   setConnectivity(newConn,newConnI,true);
4773   return true;
4774 }
4775
4776 /*!
4777  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4778  * A cell is considered to be oriented correctly if an angle between its
4779  * normal vector and a given vector is less than \c PI / \c 2.
4780  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4781  *         cells. 
4782  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4783  *         checked.
4784  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4785  *         is not cleared before filling in.
4786  *  \throw If \a this->getMeshDimension() != 2.
4787  *  \throw If \a this->getSpaceDimension() != 3.
4788  *
4789  *  \if ENABLE_EXAMPLES
4790  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4791  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4792  *  \endif
4793  */
4794 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4795 {
4796   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4797     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4798   int nbOfCells=getNumberOfCells();
4799   const int *conn=_nodal_connec->begin();
4800   const int *connI=_nodal_connec_index->begin();
4801   const double *coordsPtr=_coords->begin();
4802   for(int i=0;i<nbOfCells;i++)
4803     {
4804       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4805       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4806         {
4807           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4808           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4809             cells.push_back(i);
4810         }
4811     }
4812 }
4813
4814 /*!
4815  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4816  * considered to be oriented correctly if an angle between its normal vector and a
4817  * given vector is less than \c PI / \c 2. 
4818  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4819  *         cells. 
4820  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4821  *         checked.
4822  *  \throw If \a this->getMeshDimension() != 2.
4823  *  \throw If \a this->getSpaceDimension() != 3.
4824  *
4825  *  \if ENABLE_EXAMPLES
4826  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4827  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4828  *  \endif
4829  *
4830  *  \sa changeOrientationOfCells
4831  */
4832 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4833 {
4834   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4835     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4836   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4837   const int *connI(_nodal_connec_index->begin());
4838   const double *coordsPtr(_coords->begin());
4839   bool isModified(false);
4840   for(int i=0;i<nbOfCells;i++)
4841     {
4842       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4843       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4844         {
4845           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4846           bool isQuadratic(cm.isQuadratic());
4847           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4848             {
4849               isModified=true;
4850               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4851             }
4852         }
4853     }
4854   if(isModified)
4855     _nodal_connec->declareAsNew();
4856   updateTime();
4857 }
4858
4859 /*!
4860  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4861  *
4862  * \sa orientCorrectly2DCells
4863  */
4864 void MEDCouplingUMesh::changeOrientationOfCells()
4865 {
4866   int mdim(getMeshDimension());
4867   if(mdim!=2 && mdim!=1)
4868     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4869   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4870   const int *connI(_nodal_connec_index->begin());
4871   if(mdim==2)
4872     {//2D
4873       for(int i=0;i<nbOfCells;i++)
4874         {
4875           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4876           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4877           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4878         }
4879     }
4880   else
4881     {//1D
4882       for(int i=0;i<nbOfCells;i++)
4883         {
4884           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4885           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4886           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4887         }
4888     }
4889 }
4890
4891 /*!
4892  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4893  * oriented facets. The normal vector of the facet should point out of the cell.
4894  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4895  *         is not cleared before filling in.
4896  *  \throw If \a this->getMeshDimension() != 3.
4897  *  \throw If \a this->getSpaceDimension() != 3.
4898  *  \throw If the coordinates array is not set.
4899  *  \throw If the nodal connectivity of cells is not defined.
4900  *
4901  *  \if ENABLE_EXAMPLES
4902  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4903  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4904  *  \endif
4905  */
4906 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4907 {
4908   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4909     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4910   int nbOfCells=getNumberOfCells();
4911   const int *conn=_nodal_connec->begin();
4912   const int *connI=_nodal_connec_index->begin();
4913   const double *coordsPtr=_coords->begin();
4914   for(int i=0;i<nbOfCells;i++)
4915     {
4916       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4917       if(type==INTERP_KERNEL::NORM_POLYHED)
4918         {
4919           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4920             cells.push_back(i);
4921         }
4922     }
4923 }
4924
4925 /*!
4926  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4927  * out of the cell. 
4928  *  \throw If \a this->getMeshDimension() != 3.
4929  *  \throw If \a this->getSpaceDimension() != 3.
4930  *  \throw If the coordinates array is not set.
4931  *  \throw If the nodal connectivity of cells is not defined.
4932  *  \throw If the reparation fails.
4933  *
4934  *  \if ENABLE_EXAMPLES
4935  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4936  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4937  *  \endif
4938  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4939  */
4940 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4941 {
4942   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4943     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4944   int nbOfCells=getNumberOfCells();
4945   int *conn=_nodal_connec->getPointer();
4946   const int *connI=_nodal_connec_index->begin();
4947   const double *coordsPtr=_coords->begin();
4948   for(int i=0;i<nbOfCells;i++)
4949     {
4950       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4951       if(type==INTERP_KERNEL::NORM_POLYHED)
4952         {
4953           try
4954           {
4955               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4956                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4957           }
4958           catch(INTERP_KERNEL::Exception& e)
4959           {
4960               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4961               throw INTERP_KERNEL::Exception(oss.str());
4962           }
4963         }
4964     }
4965   updateTime();
4966 }
4967
4968 /*!
4969  * This method invert orientation of all cells in \a this. 
4970  * After calling this method the absolute value of measure of cells in \a this are the same than before calling.
4971  * This method only operates on the connectivity so coordinates are not touched at all.
4972  */
4973 void MEDCouplingUMesh::invertOrientationOfAllCells()
4974 {
4975   checkConnectivityFullyDefined();
4976   std::set<INTERP_KERNEL::NormalizedCellType> gts(getAllGeoTypes());
4977   int *conn(_nodal_connec->getPointer());
4978   const int *conni(_nodal_connec_index->begin());
4979   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator gt=gts.begin();gt!=gts.end();gt++)
4980     {
4981       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::OrientationInverter> oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt));
4982       MCAuto<DataArrayInt> cwt(giveCellsWithType(*gt));
4983       for(const int *it=cwt->begin();it!=cwt->end();it++)
4984         oi->operate(conn+conni[*it]+1,conn+conni[*it+1]);
4985     }
4986   updateTime();
4987 }
4988
4989 /*!
4990  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4991  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4992  * according to which the first facet of the cell should be oriented to have the normal vector
4993  * pointing out of cell.
4994  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4995  *         cells. The caller is to delete this array using decrRef() as it is no more
4996  *         needed. 
4997  *  \throw If \a this->getMeshDimension() != 3.
4998  *  \throw If \a this->getSpaceDimension() != 3.
4999  *  \throw If the coordinates array is not set.
5000  *  \throw If the nodal connectivity of cells is not defined.
5001  *
5002  *  \if ENABLE_EXAMPLES
5003  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5004  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5005  *  \endif
5006  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5007  */
5008 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5009 {
5010   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5011   if(getMeshDimension()!=3)
5012     throw INTERP_KERNEL::Exception(msg);
5013   int spaceDim=getSpaceDimension();
5014   if(spaceDim!=3)
5015     throw INTERP_KERNEL::Exception(msg);
5016   //
5017   int nbOfCells=getNumberOfCells();
5018   int *conn=_nodal_connec->getPointer();
5019   const int *connI=_nodal_connec_index->begin();
5020   const double *coo=getCoords()->begin();
5021   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5022   for(int i=0;i<nbOfCells;i++)
5023     {
5024       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5025       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5026         {
5027           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5028             {
5029               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5030               cells->pushBackSilent(i);
5031             }
5032         }
5033     }
5034   return cells.retn();
5035 }
5036
5037 /*!
5038  * This method is a faster method to correct orientation of all 3D cells in \a this.
5039  * 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.
5040  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
5041  * 
5042  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5043  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5044  */
5045 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5046 {
5047   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5048     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5049   int nbOfCells=getNumberOfCells();
5050   int *conn=_nodal_connec->getPointer();
5051   const int *connI=_nodal_connec_index->begin();
5052   const double *coordsPtr=_coords->begin();
5053   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5054   for(int i=0;i<nbOfCells;i++)
5055     {
5056       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5057       switch(type)
5058       {
5059         case INTERP_KERNEL::NORM_TETRA4:
5060           {
5061             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5062               {
5063                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5064                 ret->pushBackSilent(i);
5065               }
5066             break;
5067           }
5068         case INTERP_KERNEL::NORM_PYRA5:
5069           {
5070             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5071               {
5072                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5073                 ret->pushBackSilent(i);
5074               }
5075             break;
5076           }
5077         case INTERP_KERNEL::NORM_PENTA6:
5078         case INTERP_KERNEL::NORM_HEXA8:
5079         case INTERP_KERNEL::NORM_HEXGP12:
5080           {
5081             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5082               {
5083                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5084                 ret->pushBackSilent(i);
5085               }
5086             break;
5087           }
5088         case INTERP_KERNEL::NORM_POLYHED:
5089           {
5090             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5091               {
5092                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5093                 ret->pushBackSilent(i);
5094               }
5095             break;
5096           }
5097         default:
5098           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 !");
5099       }
5100     }
5101   updateTime();
5102   return ret.retn();
5103 }
5104
5105 /*!
5106  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5107  * If it is not the case an exception will be thrown.
5108  * This method is fast because the first cell of \a this is used to compute the plane.
5109  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5110  * \param pos output of size at least 3 used to store a point owned of searched plane.
5111  */
5112 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5113 {
5114   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5115     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5116   const int *conn=_nodal_connec->begin();
5117   const int *connI=_nodal_connec_index->begin();
5118   const double *coordsPtr=_coords->begin();
5119   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5120   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5121 }
5122
5123 /*!
5124  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5125  * cells. Currently cells of the following types are treated:
5126  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5127  * For a cell of other type an exception is thrown.
5128  * Space dimension of a 2D mesh can be either 2 or 3.
5129  * The Edge Ratio of a cell \f$t\f$ is: 
5130  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5131  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5132  *  the smallest edge lengths of \f$t\f$.
5133  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5134  *          cells and one time, lying on \a this mesh. The caller is to delete this
5135  *          field using decrRef() as it is no more needed. 
5136  *  \throw If the coordinates array is not set.
5137  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5138  *  \throw If the connectivity data array has more than one component.
5139  *  \throw If the connectivity data array has a named component.
5140  *  \throw If the connectivity index data array has more than one component.
5141  *  \throw If the connectivity index data array has a named component.
5142  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5143  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5144  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5145  */
5146 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5147 {
5148   checkConsistencyLight();
5149   int spaceDim=getSpaceDimension();
5150   int meshDim=getMeshDimension();
5151   if(spaceDim!=2 && spaceDim!=3)
5152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5153   if(meshDim!=2 && meshDim!=3)
5154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5155   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5156   ret->setMesh(this);
5157   int nbOfCells=getNumberOfCells();
5158   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5159   arr->alloc(nbOfCells,1);
5160   double *pt=arr->getPointer();
5161   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5162   const int *conn=_nodal_connec->begin();
5163   const int *connI=_nodal_connec_index->begin();
5164   const double *coo=_coords->begin();
5165   double tmp[12];
5166   for(int i=0;i<nbOfCells;i++,pt++)
5167     {
5168       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5169       switch(t)
5170       {
5171         case INTERP_KERNEL::NORM_TRI3:
5172           {
5173             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5174             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5175             break;
5176           }
5177         case INTERP_KERNEL::NORM_QUAD4:
5178           {
5179             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5180             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5181             break;
5182           }
5183         case INTERP_KERNEL::NORM_TETRA4:
5184           {
5185             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5186             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5187             break;
5188           }
5189         default:
5190           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5191       }
5192       conn+=connI[i+1]-connI[i];
5193     }
5194   ret->setName("EdgeRatio");
5195   ret->synchronizeTimeWithSupport();
5196   return ret.retn();
5197 }
5198
5199 /*!
5200  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5201  * cells. Currently cells of the following types are treated:
5202  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5203  * For a cell of other type an exception is thrown.
5204  * Space dimension of a 2D mesh can be either 2 or 3.
5205  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5206  *          cells and one time, lying on \a this mesh. The caller is to delete this
5207  *          field using decrRef() as it is no more needed. 
5208  *  \throw If the coordinates array is not set.
5209  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5210  *  \throw If the connectivity data array has more than one component.
5211  *  \throw If the connectivity data array has a named component.
5212  *  \throw If the connectivity index data array has more than one component.
5213  *  \throw If the connectivity index data array has a named component.
5214  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5215  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5216  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5217  */
5218 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5219 {
5220   checkConsistencyLight();
5221   int spaceDim=getSpaceDimension();
5222   int meshDim=getMeshDimension();
5223   if(spaceDim!=2 && spaceDim!=3)
5224     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5225   if(meshDim!=2 && meshDim!=3)
5226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5227   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5228   ret->setMesh(this);
5229   int nbOfCells=getNumberOfCells();
5230   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5231   arr->alloc(nbOfCells,1);
5232   double *pt=arr->getPointer();
5233   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5234   const int *conn=_nodal_connec->begin();
5235   const int *connI=_nodal_connec_index->begin();
5236   const double *coo=_coords->begin();
5237   double tmp[12];
5238   for(int i=0;i<nbOfCells;i++,pt++)
5239     {
5240       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5241       switch(t)
5242       {
5243         case INTERP_KERNEL::NORM_TRI3:
5244           {
5245             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5246             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5247             break;
5248           }
5249         case INTERP_KERNEL::NORM_QUAD4:
5250           {
5251             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5252             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5253             break;
5254           }
5255         case INTERP_KERNEL::NORM_TETRA4:
5256           {
5257             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5258             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5259             break;
5260           }
5261         default:
5262           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5263       }
5264       conn+=connI[i+1]-connI[i];
5265     }
5266   ret->setName("AspectRatio");
5267   ret->synchronizeTimeWithSupport();
5268   return ret.retn();
5269 }
5270
5271 /*!
5272  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5273  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5274  * in 3D space. Currently only cells of the following types are
5275  * treated: INTERP_KERNEL::NORM_QUAD4.
5276  * For a cell of other type an exception is thrown.
5277  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5278  * Defining
5279  * \f$t=\vec{da}\times\vec{ab}\f$,
5280  * \f$u=\vec{ab}\times\vec{bc}\f$
5281  * \f$v=\vec{bc}\times\vec{cd}\f$
5282  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5283  *  \f[
5284  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5285  *  \f]
5286  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5287  *          cells and one time, lying on \a this mesh. The caller is to delete this
5288  *          field using decrRef() as it is no more needed. 
5289  *  \throw If the coordinates array is not set.
5290  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5291  *  \throw If the connectivity data array has more than one component.
5292  *  \throw If the connectivity data array has a named component.
5293  *  \throw If the connectivity index data array has more than one component.
5294  *  \throw If the connectivity index data array has a named component.
5295  *  \throw If \a this->getMeshDimension() != 2.
5296  *  \throw If \a this->getSpaceDimension() != 3.
5297  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5298  */
5299 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5300 {
5301   checkConsistencyLight();
5302   int spaceDim=getSpaceDimension();
5303   int meshDim=getMeshDimension();
5304   if(spaceDim!=3)
5305     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5306   if(meshDim!=2)
5307     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5308   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5309   ret->setMesh(this);
5310   int nbOfCells=getNumberOfCells();
5311   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5312   arr->alloc(nbOfCells,1);
5313   double *pt=arr->getPointer();
5314   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5315   const int *conn=_nodal_connec->begin();
5316   const int *connI=_nodal_connec_index->begin();
5317   const double *coo=_coords->begin();
5318   double tmp[12];
5319   for(int i=0;i<nbOfCells;i++,pt++)
5320     {
5321       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5322       switch(t)
5323       {
5324         case INTERP_KERNEL::NORM_QUAD4:
5325           {
5326             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5327             *pt=INTERP_KERNEL::quadWarp(tmp);
5328             break;
5329           }
5330         default:
5331           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5332       }
5333       conn+=connI[i+1]-connI[i];
5334     }
5335   ret->setName("Warp");
5336   ret->synchronizeTimeWithSupport();
5337   return ret.retn();
5338 }
5339
5340
5341 /*!
5342  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5343  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5344  * treated: INTERP_KERNEL::NORM_QUAD4.
5345  * The skew is computed as follow for a quad with points (a,b,c,d): let
5346  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5347  * then the skew is computed as:
5348  *  \f[
5349  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5350  *  \f]
5351  *
5352  * For a cell of other type an exception is thrown.
5353  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5354  *          cells and one time, lying on \a this mesh. The caller is to delete this
5355  *          field using decrRef() as it is no more needed. 
5356  *  \throw If the coordinates array is not set.
5357  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5358  *  \throw If the connectivity data array has more than one component.
5359  *  \throw If the connectivity data array has a named component.
5360  *  \throw If the connectivity index data array has more than one component.
5361  *  \throw If the connectivity index data array has a named component.
5362  *  \throw If \a this->getMeshDimension() != 2.
5363  *  \throw If \a this->getSpaceDimension() != 3.
5364  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5365  */
5366 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5367 {
5368   checkConsistencyLight();
5369   int spaceDim=getSpaceDimension();
5370   int meshDim=getMeshDimension();
5371   if(spaceDim!=3)
5372     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5373   if(meshDim!=2)
5374     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5375   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5376   ret->setMesh(this);
5377   int nbOfCells=getNumberOfCells();
5378   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5379   arr->alloc(nbOfCells,1);
5380   double *pt=arr->getPointer();
5381   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5382   const int *conn=_nodal_connec->begin();
5383   const int *connI=_nodal_connec_index->begin();
5384   const double *coo=_coords->begin();
5385   double tmp[12];
5386   for(int i=0;i<nbOfCells;i++,pt++)
5387     {
5388       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5389       switch(t)
5390       {
5391         case INTERP_KERNEL::NORM_QUAD4:
5392           {
5393             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5394             *pt=INTERP_KERNEL::quadSkew(tmp);
5395             break;
5396           }
5397         default:
5398           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5399       }
5400       conn+=connI[i+1]-connI[i];
5401     }
5402   ret->setName("Skew");
5403   ret->synchronizeTimeWithSupport();
5404   return ret.retn();
5405 }
5406
5407 /*!
5408  * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
5409  *
5410  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5411  *
5412  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5413  */
5414 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5415 {
5416   checkConsistencyLight();
5417   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5418   ret->setMesh(this);
5419   std::set<INTERP_KERNEL::NormalizedCellType> types;
5420   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5421   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5422   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5423   arr->alloc(nbCells,1);
5424   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5425     {
5426       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5427       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5428       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5429     }
5430   ret->setArray(arr);
5431   ret->setName("Diameter");
5432   return ret.retn();
5433 }
5434
5435 /*!
5436  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5437  * 
5438  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
5439  *                         For all other cases this input parameter is ignored.
5440  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5441  * 
5442  * \throw If \a this is not fully set (coordinates and connectivity).
5443  * \throw If a cell in \a this has no valid nodeId.
5444  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5445  */
5446 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5447 {
5448   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5449   if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3))  // Compute refined boundary box for quadratic elements only in 2D.
5450     return getBoundingBoxForBBTreeFast();
5451   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5452     {
5453       bool presenceOfQuadratic(false);
5454       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5455         {
5456           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5457           if(cm.isQuadratic())
5458             presenceOfQuadratic=true;
5459         }
5460       if(!presenceOfQuadratic)
5461         return getBoundingBoxForBBTreeFast();
5462       if(mDim==2 && sDim==2)
5463         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5464       else
5465         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5466     }
5467   throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
5468 }
5469
5470 /*!
5471  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5472  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5473  * 
5474  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5475  * 
5476  * \throw If \a this is not fully set (coordinates and connectivity).
5477  * \throw If a cell in \a this has no valid nodeId.
5478  */
5479 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5480 {
5481   checkFullyDefined();
5482   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5483   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5484   double *bbox(ret->getPointer());
5485   for(int i=0;i<nbOfCells*spaceDim;i++)
5486     {
5487       bbox[2*i]=std::numeric_limits<double>::max();
5488       bbox[2*i+1]=-std::numeric_limits<double>::max();
5489     }
5490   const double *coordsPtr(_coords->begin());
5491   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5492   for(int i=0;i<nbOfCells;i++)
5493     {
5494       int offset=connI[i]+1;
5495       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5496       for(int j=0;j<nbOfNodesForCell;j++)
5497         {
5498           int nodeId=conn[offset+j];
5499           if(nodeId>=0 && nodeId<nbOfNodes)
5500             {
5501               for(int k=0;k<spaceDim;k++)
5502                 {
5503                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5504                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5505                 }
5506               kk++;
5507             }
5508         }
5509       if(kk==0)
5510         {
5511           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5512           throw INTERP_KERNEL::Exception(oss.str());
5513         }
5514     }
5515   return ret.retn();
5516 }
5517
5518 /*!
5519  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5520  * useful for 2D meshes having quadratic cells
5521  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5522  * the two extremities of the arc of circle).
5523  * 
5524  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
5525  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5526  * \throw If \a this is not fully defined.
5527  * \throw If \a this is not a mesh with meshDimension equal to 2.
5528  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5529  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5530  */
5531 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5532 {
5533   checkFullyDefined();
5534   INTERP_KERNEL::QuadraticPlanarPrecision arcPrec(arcDetEps);
5535
5536   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5537   if(spaceDim!=2 || mDim!=2)
5538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
5539   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5540   double *bbox(ret->getPointer());
5541   const double *coords(_coords->begin());
5542   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5543   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5544     {
5545       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5546       int sz(connI[1]-connI[0]-1);
5547       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5548       INTERP_KERNEL::QuadraticPolygon *pol(0);
5549       for(int j=0;j<sz;j++)
5550         {
5551           int nodeId(conn[*connI+1+j]);
5552           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5553         }
5554       if(!cm.isQuadratic())
5555         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5556       else
5557         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5558       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5559       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5560     }
5561   return ret.retn();
5562 }
5563
5564 /*!
5565  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5566  * useful for 2D meshes having quadratic cells
5567  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5568  * the two extremities of the arc of circle).
5569  * 
5570  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
5571  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5572  * \throw If \a this is not fully defined.
5573  * \throw If \a this is not a mesh with meshDimension equal to 1.
5574  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5575  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5576  */
5577 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5578 {
5579   checkFullyDefined();
5580   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5581   if(spaceDim!=2 || mDim!=1)
5582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
5583   INTERP_KERNEL::QuadraticPlanarPrecision arcPrec(arcDetEps);
5584   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5585   double *bbox(ret->getPointer());
5586   const double *coords(_coords->begin());
5587   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5588   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5589     {
5590       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5591       int sz(connI[1]-connI[0]-1);
5592       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5593       INTERP_KERNEL::Edge *edge(0);
5594       for(int j=0;j<sz;j++)
5595         {
5596           int nodeId(conn[*connI+1+j]);
5597           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5598         }
5599       if(!cm.isQuadratic())
5600         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5601       else
5602         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5603       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5604       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5605     }
5606   return ret.retn();
5607 }
5608
5609 /// @cond INTERNAL
5610
5611 namespace MEDCouplingImpl
5612 {
5613   class ConnReader
5614   {
5615   public:
5616     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5617     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5618   private:
5619     const int *_conn;
5620     int _val;
5621   };
5622
5623   class ConnReader2
5624   {
5625   public:
5626     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5627     bool operator() (const int& pos) { return _conn[pos]==_val; }
5628   private:
5629     const int *_conn;
5630     int _val;
5631   };
5632 }
5633
5634 /// @endcond
5635
5636 /*!
5637  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5638  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5639  * \a this is composed in cell types.
5640  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5641  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5642  * This parameter is kept only for compatibility with other method listed above.
5643  */
5644 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5645 {
5646   checkConnectivityFullyDefined();
5647   const int *conn=_nodal_connec->begin();
5648   const int *connI=_nodal_connec_index->begin();
5649   const int *work=connI;
5650   int nbOfCells=getNumberOfCells();
5651   std::size_t n=getAllGeoTypes().size();
5652   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5653   std::set<INTERP_KERNEL::NormalizedCellType> types;
5654   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5655     {
5656       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5657       if(types.find(typ)!=types.end())
5658         {
5659           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5660           oss << " is not contiguous !";
5661           throw INTERP_KERNEL::Exception(oss.str());
5662         }
5663       types.insert(typ);
5664       ret[3*i]=typ;
5665       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5666       ret[3*i+1]=(int)std::distance(work,work2);
5667       work=work2;
5668     }
5669   return ret;
5670 }
5671
5672 /*!
5673  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5674  * only for types cell, type node is not managed.
5675  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5676  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5677  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5678  * If 2 or more same geometric type is in \a code and exception is thrown too.
5679  *
5680  * This method firstly checks
5681  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5682  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5683  * an exception is thrown too.
5684  * 
5685  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5686  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5687  * and a DataArrayInt instance is returned that the user has the responsibility to deallocate.
5688  */
5689 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5690 {
5691   if(code.empty())
5692     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5693   std::size_t sz=code.size();
5694   std::size_t n=sz/3;
5695   if(sz%3!=0)
5696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5697   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5698   int nb=0;
5699   bool isNoPflUsed=true;
5700   for(std::size_t i=0;i<n;i++)
5701     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5702       {
5703         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5704         nb+=code[3*i+1];
5705         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5706           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5707         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5708       }
5709   if(types.size()!=n)
5710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5711   if(isNoPflUsed)
5712     {
5713       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5714         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5715       if(types.size()==_types.size())
5716         return 0;
5717     }
5718   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5719   ret->alloc(nb,1);
5720   int *retPtr=ret->getPointer();
5721   const int *connI=_nodal_connec_index->begin();
5722   const int *conn=_nodal_connec->begin();
5723   int nbOfCells=getNumberOfCells();
5724   const int *i=connI;
5725   int kk=0;
5726   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5727     {
5728       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5729       int offset=(int)std::distance(connI,i);
5730       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5731       int nbOfCellsOfCurType=(int)std::distance(i,j);
5732       if(code[3*kk+2]==-1)
5733         for(int k=0;k<nbOfCellsOfCurType;k++)
5734           *retPtr++=k+offset;
5735       else
5736         {
5737           int idInIdsPerType=code[3*kk+2];
5738           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5739             {
5740               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5741               if(zePfl)
5742                 {
5743                   zePfl->checkAllocated();
5744                   if(zePfl->getNumberOfComponents()==1)
5745                     {
5746                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5747                         {
5748                           if(*k>=0 && *k<nbOfCellsOfCurType)
5749                             *retPtr=(*k)+offset;
5750                           else
5751                             {
5752                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5753                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5754                               throw INTERP_KERNEL::Exception(oss.str());
5755                             }
5756                         }
5757                     }
5758                   else
5759                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5760                 }
5761               else
5762                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5763             }
5764           else
5765             {
5766               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5767               oss << " should be in [0," << idsPerType.size() << ") !";
5768               throw INTERP_KERNEL::Exception(oss.str());
5769             }
5770         }
5771       i=j;
5772     }
5773   return ret.retn();
5774 }
5775
5776 /*!
5777  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5778  * 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.
5779  * 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.
5780  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5781  * 
5782  * \param [in] profile
5783  * \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.
5784  * \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,
5785  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5786  * \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.
5787  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5788  * \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
5789  */
5790 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType, bool smartPflKiller) const
5791 {
5792   if(!profile)
5793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5794   if(profile->getNumberOfComponents()!=1)
5795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5796   checkConnectivityFullyDefined();
5797   const int *conn=_nodal_connec->begin();
5798   const int *connI=_nodal_connec_index->begin();
5799   int nbOfCells=getNumberOfCells();
5800   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5801   std::vector<int> typeRangeVals(1);
5802   for(const int *i=connI;i!=connI+nbOfCells;)
5803     {
5804       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5805       if(std::find(types.begin(),types.end(),curType)!=types.end())
5806         {
5807           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5808         }
5809       types.push_back(curType);
5810       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5811       typeRangeVals.push_back((int)std::distance(connI,i));
5812     }
5813   //
5814   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5815   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5816   MCAuto<DataArrayInt> tmp0=castArr;
5817   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5818   MCAuto<DataArrayInt> tmp2=castsPresent;
5819   //
5820   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5821   code.resize(3*nbOfCastsFinal);
5822   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5823   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5824   for(int i=0;i<nbOfCastsFinal;i++)
5825     {
5826       int castId=castsPresent->getIJ(i,0);
5827       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5828       idsInPflPerType2.push_back(tmp3);
5829       code[3*i]=(int)types[castId];
5830       code[3*i+1]=tmp3->getNumberOfTuples();
5831       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5832       if(!smartPflKiller || !tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5833         {
5834           tmp4->copyStringInfoFrom(*profile);
5835           idsPerType2.push_back(tmp4);
5836           code[3*i+2]=(int)idsPerType2.size()-1;
5837         }
5838       else
5839         {
5840           code[3*i+2]=-1;
5841         }
5842     }
5843   std::size_t sz2=idsInPflPerType2.size();
5844   idsInPflPerType.resize(sz2);
5845   for(std::size_t i=0;i<sz2;i++)
5846     {
5847       DataArrayInt *locDa=idsInPflPerType2[i];
5848       locDa->incrRef();
5849       idsInPflPerType[i]=locDa;
5850     }
5851   std::size_t sz=idsPerType2.size();
5852   idsPerType.resize(sz);
5853   for(std::size_t i=0;i<sz;i++)
5854     {
5855       DataArrayInt *locDa=idsPerType2[i];
5856       locDa->incrRef();
5857       idsPerType[i]=locDa;
5858     }
5859 }
5860
5861 /*!
5862  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5863  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5864  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5865  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::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.
5866  */
5867 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5868 {
5869   checkFullyDefined();
5870   nM1LevMesh->checkFullyDefined();
5871   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5873   if(_coords!=nM1LevMesh->getCoords())
5874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5875   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5876   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5877   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5878   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5879   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5880   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5881   tmp->setConnectivity(tmp0,tmp1);
5882   tmp->renumberCells(ret0->begin(),false);
5883   revDesc=tmp->getNodalConnectivity();
5884   revDescIndx=tmp->getNodalConnectivityIndex();
5885   DataArrayInt *ret=0;
5886   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5887     {
5888       int tmp2;
5889       ret->getMaxValue(tmp2);
5890       ret->decrRef();
5891       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5892       throw INTERP_KERNEL::Exception(oss.str());
5893     }
5894   nM1LevMeshIds=ret;
5895   //
5896   revDesc->incrRef();
5897   revDescIndx->incrRef();
5898   ret1->incrRef();
5899   ret0->incrRef();
5900   meshnM1Old2New=ret0;
5901   return ret1;
5902 }
5903
5904 /*!
5905  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5906  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5907  * in "Old to New" mode.
5908  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5909  *          this array using decrRef() as it is no more needed.
5910  *  \throw If the nodal connectivity of cells is not defined.
5911  */
5912 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5913 {
5914   checkConnectivityFullyDefined();
5915   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5916   renumberCells(ret->begin(),false);
5917   return ret.retn();
5918 }
5919
5920 /*!
5921  * This methods checks that cells are sorted by their types.
5922  * This method makes asumption (no check) that connectivity is correctly set before calling.
5923  */
5924 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5925 {
5926   checkFullyDefined();
5927   const int *conn=_nodal_connec->begin();
5928   const int *connI=_nodal_connec_index->begin();
5929   int nbOfCells=getNumberOfCells();
5930   std::set<INTERP_KERNEL::NormalizedCellType> types;
5931   for(const int *i=connI;i!=connI+nbOfCells;)
5932     {
5933       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5934       if(types.find(curType)!=types.end())
5935         return false;
5936       types.insert(curType);
5937       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5938     }
5939   return true;
5940 }
5941
5942 /*!
5943  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5944  * The geometric type order is specified by MED file.
5945  * 
5946  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5947  */
5948 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5949 {
5950   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5951 }
5952
5953 /*!
5954  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5955  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5956  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5957  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5958  */
5959 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5960 {
5961   checkFullyDefined();
5962   const int *conn=_nodal_connec->begin();
5963   const int *connI=_nodal_connec_index->begin();
5964   int nbOfCells=getNumberOfCells();
5965   if(nbOfCells==0)
5966     return true;
5967   int lastPos=-1;
5968   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5969   for(const int *i=connI;i!=connI+nbOfCells;)
5970     {
5971       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5972       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5973       if(isTypeExists!=orderEnd)
5974         {
5975           int pos=(int)std::distance(orderBg,isTypeExists);
5976           if(pos<=lastPos)
5977             return false;
5978           lastPos=pos;
5979           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5980         }
5981       else
5982         {
5983           if(sg.find(curType)==sg.end())
5984             {
5985               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5986               sg.insert(curType);
5987             }
5988           else
5989             return false;
5990         }
5991     }
5992   return true;
5993 }
5994
5995 /*!
5996  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5997  * 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
5998  * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurrence of type in 'this'.
5999  */
6000 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6001 {
6002   checkConnectivityFullyDefined();
6003   int nbOfCells=getNumberOfCells();
6004   const int *conn=_nodal_connec->begin();
6005   const int *connI=_nodal_connec_index->begin();
6006   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
6007   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
6008   tmpa->alloc(nbOfCells,1);
6009   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6010   tmpb->fillWithZero();
6011   int *tmp=tmpa->getPointer();
6012   int *tmp2=tmpb->getPointer();
6013   for(const int *i=connI;i!=connI+nbOfCells;i++)
6014     {
6015       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6016       if(where!=orderEnd)
6017         {
6018           int pos=(int)std::distance(orderBg,where);
6019           tmp2[pos]++;
6020           tmp[std::distance(connI,i)]=pos;
6021         }
6022       else
6023         {
6024           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6025           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6026           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6027           throw INTERP_KERNEL::Exception(oss.str());
6028         }
6029     }
6030   nbPerType=tmpb.retn();
6031   return tmpa.retn();
6032 }
6033
6034 /*!
6035  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6036  *
6037  * \return a new object containing the old to new correspondence.
6038  *
6039  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6040  */
6041 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6042 {
6043   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6044 }
6045
6046 /*!
6047  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specified by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
6048  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6049  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6050  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6051  */
6052 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6053 {
6054   DataArrayInt *nbPerType=0;
6055   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6056   nbPerType->decrRef();
6057   return tmpa->buildPermArrPerLevel();
6058 }
6059
6060 /*!
6061  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6062  * The number of cells remains unchanged after the call of this method.
6063  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6064  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6065  *
6066  * \return the array giving the correspondence old to new.
6067  */
6068 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6069 {
6070   checkFullyDefined();
6071   computeTypes();
6072   const int *conn=_nodal_connec->begin();
6073   const int *connI=_nodal_connec_index->begin();
6074   int nbOfCells=getNumberOfCells();
6075   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6076   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6077     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6078       {
6079         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6080         types.push_back(curType);
6081         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6082       }
6083   DataArrayInt *ret=DataArrayInt::New();
6084   ret->alloc(nbOfCells,1);
6085   int *retPtr=ret->getPointer();
6086   std::fill(retPtr,retPtr+nbOfCells,-1);
6087   int newCellId=0;
6088   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6089     {
6090       for(const int *i=connI;i!=connI+nbOfCells;i++)
6091         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6092           retPtr[std::distance(connI,i)]=newCellId++;
6093     }
6094   renumberCells(retPtr,false);
6095   return ret;
6096 }
6097
6098 /*!
6099  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6100  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6101  * This method makes asumption that connectivity is correctly set before calling.
6102  */
6103 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6104 {
6105   checkConnectivityFullyDefined();
6106   const int *conn=_nodal_connec->begin();
6107   const int *connI=_nodal_connec_index->begin();
6108   int nbOfCells=getNumberOfCells();
6109   std::vector<MEDCouplingUMesh *> ret;
6110   for(const int *i=connI;i!=connI+nbOfCells;)
6111     {
6112       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6113       int beginCellId=(int)std::distance(connI,i);
6114       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
6115       int endCellId=(int)std::distance(connI,i);
6116       int sz=endCellId-beginCellId;
6117       int *cells=new int[sz];
6118       for(int j=0;j<sz;j++)
6119         cells[j]=beginCellId+j;
6120       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6121       delete [] cells;
6122       ret.push_back(m);
6123     }
6124   return ret;
6125 }
6126
6127 /*!
6128  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6129  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6130  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6131  *
6132  * \return a newly allocated instance, that the caller must manage.
6133  * \throw If \a this contains more than one geometric type.
6134  * \throw If the nodal connectivity of \a this is not fully defined.
6135  * \throw If the internal data is not coherent.
6136  */
6137 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6138 {
6139   checkConnectivityFullyDefined();
6140   if(_types.size()!=1)
6141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6142   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6143   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6144   ret->setCoords(getCoords());
6145   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6146   if(retC)
6147     {
6148       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6149       retC->setNodalConnectivity(c);
6150     }
6151   else
6152     {
6153       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6154       if(!retD)
6155         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6156       DataArrayInt *c=0,*ci=0;
6157       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6158       MCAuto<DataArrayInt> cs(c),cis(ci);
6159       retD->setNodalConnectivity(cs,cis);
6160     }
6161   return ret.retn();
6162 }
6163
6164 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6165 {
6166   checkConnectivityFullyDefined();
6167   if(_types.size()!=1)
6168     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6169   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6170   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6171   if(cm.isDynamic())
6172     {
6173       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6174       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6175       throw INTERP_KERNEL::Exception(oss.str());
6176     }
6177   int nbCells=getNumberOfCells();
6178   int typi=(int)typ;
6179   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6180   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6181   int *outPtr=connOut->getPointer();
6182   const int *conn=_nodal_connec->begin();
6183   const int *connI=_nodal_connec_index->begin();
6184   nbNodesPerCell++;
6185   for(int i=0;i<nbCells;i++,connI++)
6186     {
6187       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6188         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6189       else
6190         {
6191           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 << ") !";
6192           throw INTERP_KERNEL::Exception(oss.str());
6193         }
6194     }
6195   return connOut.retn();
6196 }
6197
6198 /*!
6199  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6200  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6201  * \param nodalConn
6202  * \param nodalConnI
6203  */
6204 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6205 {
6206   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6207   checkConnectivityFullyDefined();
6208   if(_types.size()!=1)
6209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6210   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6211   if(lgth<nbCells)
6212     throw INTERP_KERNEL::Exception(msg0);
6213   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6214   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6215   int *cp(c->getPointer()),*cip(ci->getPointer());
6216   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6217   cip[0]=0;
6218   for(int i=0;i<nbCells;i++,cip++,incip++)
6219     {
6220       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6221       int delta(stop-strt);
6222       if(delta>=1)
6223         {
6224           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6225             cp=std::copy(incp+strt,incp+stop,cp);
6226           else
6227             throw INTERP_KERNEL::Exception(msg0);
6228         }
6229       else
6230         throw INTERP_KERNEL::Exception(msg0);
6231       cip[1]=cip[0]+delta;
6232     }
6233   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6234 }
6235
6236 /*!
6237  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6238  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6239  * This method is particularly useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6240  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6241  * are not used here to avoid the build of big permutation array.
6242  *
6243  * \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
6244  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6245  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6246  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6247  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6248  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6249  * \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
6250  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6251  */
6252 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6253                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6254                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6255 {
6256   std::vector<const MEDCouplingUMesh *> ms2;
6257   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6258     if(*it)
6259       {
6260         (*it)->checkConnectivityFullyDefined();
6261         ms2.push_back(*it);
6262       }
6263   if(ms2.empty())
6264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6265   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6266   int meshDim=ms2[0]->getMeshDimension();
6267   std::vector<const MEDCouplingUMesh *> m1ssm;
6268   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6269   //
6270   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6271   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6272   int fake=0,rk=0;
6273   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6274   ret1->alloc(0,1); ret2->alloc(0,1);
6275   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6276     {
6277       if(meshDim!=(*it)->getMeshDimension())
6278         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6279       if(refCoo!=(*it)->getCoords())
6280         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6281       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6282       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6283       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6284       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6285         {
6286           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6287           m1ssmSingleAuto.push_back(singleCell);
6288           m1ssmSingle.push_back(singleCell);
6289           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6290         }
6291     }
6292   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6293   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6294   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6295   for(std::size_t i=0;i<m1ssm.size();i++)
6296     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6297   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6298   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6299   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6300   return ret0.retn();
6301 }
6302
6303 /*!
6304  * This method returns a newly created DataArrayInt instance.
6305  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6306  */
6307 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6308 {
6309   checkFullyDefined();
6310   const int *conn=_nodal_connec->begin();
6311   const int *connIndex=_nodal_connec_index->begin();
6312   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6313   for(const int *w=begin;w!=end;w++)
6314     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6315       ret->pushBackSilent(*w);
6316   return ret.retn();
6317 }
6318
6319 /*!
6320  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6321  * are in [0:getNumberOfCells())
6322  */
6323 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6324 {
6325   checkFullyDefined();
6326   const int *conn=_nodal_connec->begin();
6327   const int *connI=_nodal_connec_index->begin();
6328   int nbOfCells=getNumberOfCells();
6329   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6330   int *tmp=new int[nbOfCells];
6331   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6332     {
6333       int j=0;
6334       for(const int *i=connI;i!=connI+nbOfCells;i++)
6335         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6336           tmp[std::distance(connI,i)]=j++;
6337     }
6338   DataArrayInt *ret=DataArrayInt::New();
6339   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6340   ret->copyStringInfoFrom(*da);
6341   int *retPtr=ret->getPointer();
6342   const int *daPtr=da->begin();
6343   int nbOfElems=da->getNbOfElems();
6344   for(int k=0;k<nbOfElems;k++)
6345     retPtr[k]=tmp[daPtr[k]];
6346   delete [] tmp;
6347   return ret;
6348 }
6349
6350 /*!
6351  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6352  * This method \b works \b for mesh sorted by type.
6353  * cells whose ids is in 'idsPerGeoType' array.
6354  * This method conserves coords and name of mesh.
6355  */
6356 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6357 {
6358   std::vector<int> code=getDistributionOfTypes();
6359   std::size_t nOfTypesInThis=code.size()/3;
6360   int sz=0,szOfType=0;
6361   for(std::size_t i=0;i<nOfTypesInThis;i++)
6362     {
6363       if(code[3*i]!=type)
6364         sz+=code[3*i+1];
6365       else
6366         szOfType=code[3*i+1];
6367     }
6368   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6369     if(*work<0 || *work>=szOfType)
6370       {
6371         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6372         oss << ". It should be in [0," << szOfType << ") !";
6373         throw INTERP_KERNEL::Exception(oss.str());
6374       }
6375   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6376   int *idsPtr=idsTokeep->getPointer();
6377   int offset=0;
6378   for(std::size_t i=0;i<nOfTypesInThis;i++)
6379     {
6380       if(code[3*i]!=type)
6381         for(int j=0;j<code[3*i+1];j++)
6382           *idsPtr++=offset+j;
6383       else
6384         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6385       offset+=code[3*i+1];
6386     }
6387   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6388   ret->copyTinyInfoFrom(this);
6389   return ret.retn();
6390 }
6391
6392 /*!
6393  * This method returns a vector of size 'this->getNumberOfCells()'.
6394  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6395  */
6396 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6397 {
6398   int ncell=getNumberOfCells();
6399   std::vector<bool> ret(ncell);
6400   const int *cI=getNodalConnectivityIndex()->begin();
6401   const int *c=getNodalConnectivity()->begin();
6402   for(int i=0;i<ncell;i++)
6403     {
6404       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6405       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6406       ret[i]=cm.isQuadratic();
6407     }
6408   return ret;
6409 }
6410
6411 /*!
6412  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6413  */
6414 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6415 {
6416   if(other->getType()!=UNSTRUCTURED)
6417     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6418   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6419   return MergeUMeshes(this,otherC);
6420 }
6421
6422 /*!
6423  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6424  * computed by averaging coordinates of cell nodes, so this method is not a right
6425  * choice for degenerated meshes (not well oriented, cells with measure close to zero).
6426  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6427  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6428  *          components. The caller is to delete this array using decrRef() as it is
6429  *          no more needed.
6430  *  \throw If the coordinates array is not set.
6431  *  \throw If the nodal connectivity of cells is not defined.
6432  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6433  */
6434 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6435 {
6436   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6437   int spaceDim=getSpaceDimension();
6438   int nbOfCells=getNumberOfCells();
6439   ret->alloc(nbOfCells,spaceDim);
6440   ret->copyStringInfoFrom(*getCoords());
6441   double *ptToFill=ret->getPointer();
6442   const int *nodal=_nodal_connec->begin();
6443   const int *nodalI=_nodal_connec_index->begin();
6444   const double *coor=_coords->begin();
6445   for(int i=0;i<nbOfCells;i++)
6446     {
6447       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6448       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6449       ptToFill+=spaceDim;
6450     }
6451   return ret.retn();
6452 }
6453
6454 /*!
6455  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6456  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6457  * 
6458  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6459  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6460  * 
6461  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6462  * \throw If \a this is not fully defined (coordinates and connectivity)
6463  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6464  */
6465 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6466 {
6467   checkFullyDefined();
6468   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6469   int spaceDim=getSpaceDimension();
6470   int nbOfCells=getNumberOfCells();
6471   int nbOfNodes=getNumberOfNodes();
6472   ret->alloc(nbOfCells,spaceDim);
6473   double *ptToFill=ret->getPointer();
6474   const int *nodal=_nodal_connec->begin();
6475   const int *nodalI=_nodal_connec_index->begin();
6476   const double *coor=_coords->begin();
6477   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6478     {
6479       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6480       std::fill(ptToFill,ptToFill+spaceDim,0.);
6481       if(type!=INTERP_KERNEL::NORM_POLYHED)
6482         {
6483           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6484             {
6485               if(*conn>=0 && *conn<nbOfNodes)
6486                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6487               else
6488                 {
6489                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6490                   throw INTERP_KERNEL::Exception(oss.str());
6491                 }
6492             }
6493           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6494           if(nbOfNodesInCell>0)
6495             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6496           else
6497             {
6498               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6499               throw INTERP_KERNEL::Exception(oss.str());
6500             }
6501         }
6502       else
6503         {
6504           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6505           s.erase(-1);
6506           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6507             {
6508               if(*it>=0 && *it<nbOfNodes)
6509                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6510               else
6511                 {
6512                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6513                   throw INTERP_KERNEL::Exception(oss.str());
6514                 }
6515             }
6516           if(!s.empty())
6517             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6518           else
6519             {
6520               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6521               throw INTERP_KERNEL::Exception(oss.str());
6522             }
6523         }
6524     }
6525   return ret.retn();
6526 }
6527
6528 /*!
6529  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6530  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6531  * are specified via an array of cell ids. 
6532  *  \warning Validity of the specified cell ids is not checked! 
6533  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6534  *  \param [in] begin - an array of cell ids of interest.
6535  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6536  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6537  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6538  *          caller is to delete this array using decrRef() as it is no more needed. 
6539  *  \throw If the coordinates array is not set.
6540  *  \throw If the nodal connectivity of cells is not defined.
6541  *
6542  *  \if ENABLE_EXAMPLES
6543  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6544  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6545  *  \endif
6546  */
6547 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6548 {
6549   DataArrayDouble *ret=DataArrayDouble::New();
6550   int spaceDim=getSpaceDimension();
6551   int nbOfTuple=(int)std::distance(begin,end);
6552   ret->alloc(nbOfTuple,spaceDim);
6553   double *ptToFill=ret->getPointer();
6554   double *tmp=new double[spaceDim];
6555   const int *nodal=_nodal_connec->begin();
6556   const int *nodalI=_nodal_connec_index->begin();
6557   const double *coor=_coords->begin();
6558   for(const int *w=begin;w!=end;w++)
6559     {
6560       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6561       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6562       ptToFill+=spaceDim;
6563     }
6564   delete [] tmp;
6565   return ret;
6566 }
6567
6568 /*!
6569  * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
6570  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6571  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6572  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6573  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6574  * 
6575  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6576  * \throw If spaceDim!=3 or meshDim!=2.
6577  * \throw If connectivity of \a this is invalid.
6578  * \throw If connectivity of a cell in \a this points to an invalid node.
6579  */
6580 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6581 {
6582   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6583   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6584   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6586   ret->alloc(nbOfCells,4);
6587   double *retPtr(ret->getPointer());
6588   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6589   const double *coor(_coords->begin());
6590   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6591     {
6592       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6593       if(nodalI[1]-nodalI[0]>=4)
6594         {
6595           double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6596                         coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6597                         coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}
6598           ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6599                         coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6600                         coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]};
6601           double cc[3]={aa[1]*bb[2]-aa[2]*bb[1],aa[2]*bb[0]-aa[0]*bb[2],aa[0]*bb[1]-aa[1]*bb[0]};
6602           for(int j=0;j<3;j++)
6603             {
6604               int nodeId(nodal[nodalI[0]+1+j]);
6605               if(nodeId>=0 && nodeId<nbOfNodes)
6606                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6607               else
6608                 {
6609                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6610                   throw INTERP_KERNEL::Exception(oss.str());
6611                 }
6612             }
6613           if(sqrt(cc[0]*cc[0]+cc[1]*cc[1]+cc[2]*cc[2])>1e-7)
6614             {
6615               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6616               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6617             }
6618           else
6619             {
6620               if(nodalI[1]-nodalI[0]==4)
6621                 {
6622                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !";
6623                   throw INTERP_KERNEL::Exception(oss.str());
6624                 }
6625               //
6626               double dd[3]={0.,0.,0.};
6627               for(int offset=nodalI[0]+1;offset<nodalI[1];offset++)
6628                 std::transform(coor+3*nodal[offset],coor+3*(nodal[offset]+1),dd,dd,std::plus<double>());
6629               int nbOfNodesInCell(nodalI[1]-nodalI[0]-1);
6630               std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6631               std::copy(dd,dd+3,matrix+4*2);
6632               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6633               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6634             }
6635         }
6636       else
6637         {
6638           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6639           throw INTERP_KERNEL::Exception(oss.str());
6640         }
6641     }
6642   return ret.retn();
6643 }
6644
6645 /*!
6646  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6647  * 
6648  */
6649 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6650 {
6651   if(!da)
6652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6653   da->checkAllocated();
6654   std::string name(da->getName());
6655   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6656   if(name.empty())
6657     ret->setName("Mesh");
6658   ret->setCoords(da);
6659   int nbOfTuples(da->getNumberOfTuples());
6660   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6661   c->alloc(2*nbOfTuples,1);
6662   cI->alloc(nbOfTuples+1,1);
6663   int *cp(c->getPointer()),*cip(cI->getPointer());
6664   *cip++=0;
6665   for(int i=0;i<nbOfTuples;i++)
6666     {
6667       *cp++=INTERP_KERNEL::NORM_POINT1;
6668       *cp++=i;
6669       *cip++=2*(i+1);
6670     }
6671   ret->setConnectivity(c,cI,true);
6672   return ret.retn();
6673 }
6674
6675 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6676 {
6677   if(!da)
6678     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6679   da->checkAllocated();
6680   std::string name(da->getName());
6681   MCAuto<MEDCouplingUMesh> ret;
6682   {
6683     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6684     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6685     arr->alloc(da->getNumberOfTuples());
6686     tmp->setCoordsAt(0,arr);
6687     ret=tmp->buildUnstructured();
6688   }
6689   ret->setCoords(da);
6690   if(name.empty())
6691     ret->setName("Mesh");
6692   else
6693     ret->setName(name);
6694   return ret;
6695 }
6696
6697 /*!
6698  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6699  * Cells and nodes of
6700  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6701  *  \param [in] mesh1 - the first mesh.
6702  *  \param [in] mesh2 - the second mesh.
6703  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6704  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6705  *          is no more needed.
6706  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6707  *  \throw If the coordinates array is not set in none of the meshes.
6708  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6709  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6710  */
6711 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6712 {
6713   std::vector<const MEDCouplingUMesh *> tmp(2);
6714   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6715   return MergeUMeshes(tmp);
6716 }
6717
6718 /*!
6719  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6720  * Cells and nodes of
6721  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6722  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6723  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6724  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6725  *          is no more needed.
6726  *  \throw If \a a.size() == 0.
6727  *  \throw If \a a[ *i* ] == NULL.
6728  *  \throw If the coordinates array is not set in none of the meshes.
6729  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6730  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6731  */
6732 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6733 {
6734   std::size_t sz=a.size();
6735   if(sz==0)
6736     return MergeUMeshesLL(a);
6737   for(std::size_t ii=0;ii<sz;ii++)
6738     if(!a[ii])
6739       {
6740         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6741         throw INTERP_KERNEL::Exception(oss.str());
6742       }
6743   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6744   std::vector< const MEDCouplingUMesh * > aa(sz);
6745   int spaceDim=-3;
6746   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6747     {
6748       const MEDCouplingUMesh *cur=a[i];
6749       const DataArrayDouble *coo=cur->getCoords();
6750       if(coo)
6751         spaceDim=coo->getNumberOfComponents();
6752     }
6753   if(spaceDim==-3)
6754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6755   for(std::size_t i=0;i<sz;i++)
6756     {
6757       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6758       aa[i]=bb[i];
6759     }
6760   return MergeUMeshesLL(aa);
6761 }
6762
6763 /*!
6764  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6765  * dimension and sharing the node coordinates array.
6766  * All cells of the first mesh precede all cells of the second mesh
6767  * within the result mesh.
6768  *  \param [in] mesh1 - the first mesh.
6769  *  \param [in] mesh2 - the second mesh.
6770  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6771  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6772  *          is no more needed.
6773  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6774  *  \throw If the meshes do not share the node coordinates array.
6775  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6776  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6777  */
6778 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6779 {
6780   std::vector<const MEDCouplingUMesh *> tmp(2);
6781   tmp[0]=mesh1; tmp[1]=mesh2;
6782   return MergeUMeshesOnSameCoords(tmp);
6783 }
6784
6785 /*!
6786  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6787  * dimension and sharing the node coordinates array.
6788  * All cells of the *i*-th mesh precede all cells of the
6789  * (*i*+1)-th mesh within the result mesh.
6790  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6791  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6792  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6793  *          is no more needed.
6794  *  \throw If \a a.size() == 0.
6795  *  \throw If \a a[ *i* ] == NULL.
6796  *  \throw If the meshes do not share the node coordinates array.
6797  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6798  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6799  */
6800 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6801 {
6802   if(meshes.empty())
6803     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6804   for(std::size_t ii=0;ii<meshes.size();ii++)
6805     if(!meshes[ii])
6806       {
6807         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6808         throw INTERP_KERNEL::Exception(oss.str());
6809       }
6810   const DataArrayDouble *coords=meshes.front()->getCoords();
6811   int meshDim=meshes.front()->getMeshDimension();
6812   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6813   int meshLgth=0;
6814   int meshIndexLgth=0;
6815   for(;iter!=meshes.end();iter++)
6816     {
6817       if(coords!=(*iter)->getCoords())
6818         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6819       if(meshDim!=(*iter)->getMeshDimension())
6820         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6821       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6822       meshIndexLgth+=(*iter)->getNumberOfCells();
6823     }
6824   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6825   nodal->alloc(meshLgth,1);
6826   int *nodalPtr=nodal->getPointer();
6827   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6828   nodalIndex->alloc(meshIndexLgth+1,1);
6829   int *nodalIndexPtr=nodalIndex->getPointer();
6830   int offset=0;
6831   for(iter=meshes.begin();iter!=meshes.end();iter++)
6832     {
6833       const int *nod=(*iter)->getNodalConnectivity()->begin();
6834       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6835       int nbOfCells=(*iter)->getNumberOfCells();
6836       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6837       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6838       if(iter!=meshes.begin())
6839         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6840       else
6841         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6842       offset+=meshLgth2;
6843     }
6844   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6845   ret->setName("merge");
6846   ret->setMeshDimension(meshDim);
6847   ret->setConnectivity(nodal,nodalIndex,true);
6848   ret->setCoords(coords);
6849   return ret;
6850 }
6851
6852 /*!
6853  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6854  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6855  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6856  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6857  * New" mode are returned for each input mesh.
6858  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6859  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6860  *          valid values [0,1,2], see zipConnectivityTraducer().
6861  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6862  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6863  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6864  *          no more needed.
6865  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6866  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6867  *          is no more needed.
6868  *  \throw If \a meshes.size() == 0.
6869  *  \throw If \a meshes[ *i* ] == NULL.
6870  *  \throw If the meshes do not share the node coordinates array.
6871  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6872  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6873  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6874  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6875  */
6876 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6877 {
6878   //All checks are delegated to MergeUMeshesOnSameCoords
6879   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6880   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6881   corr.resize(meshes.size());
6882   std::size_t nbOfMeshes=meshes.size();
6883   int offset=0;
6884   const int *o2nPtr=o2n->begin();
6885   for(std::size_t i=0;i<nbOfMeshes;i++)
6886     {
6887       DataArrayInt *tmp=DataArrayInt::New();
6888       int curNbOfCells=meshes[i]->getNumberOfCells();
6889       tmp->alloc(curNbOfCells,1);
6890       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6891       offset+=curNbOfCells;
6892       tmp->setName(meshes[i]->getName());
6893       corr[i]=tmp;
6894     }
6895   return ret.retn();
6896 }
6897
6898 /*!
6899  * Makes all given meshes share the nodal connectivity array. The common connectivity
6900  * array is created by concatenating the connectivity arrays of all given meshes. All
6901  * the given meshes must be of the same space dimension but dimension of cells **can
6902  * differ**. This method is particularly useful in MEDLoader context to build a \ref
6903  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6904  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6905  *  \param [in,out] meshes - a vector of meshes to update.
6906  *  \throw If any of \a meshes is NULL.
6907  *  \throw If the coordinates array is not set in any of \a meshes.
6908  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6909  *  \throw If \a meshes are of different space dimension.
6910  */
6911 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6912 {
6913   std::size_t sz=meshes.size();
6914   if(sz==0 || sz==1)
6915     return;
6916   std::vector< const DataArrayDouble * > coords(meshes.size());
6917   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6918   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6919     {
6920       if((*it))
6921         {
6922           (*it)->checkConnectivityFullyDefined();
6923           const DataArrayDouble *coo=(*it)->getCoords();
6924           if(coo)
6925             *it2=coo;
6926           else
6927             {
6928               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6929               oss << " has no coordinate array defined !";
6930               throw INTERP_KERNEL::Exception(oss.str());
6931             }
6932         }
6933       else
6934         {
6935           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6936           oss << " is null !";
6937           throw INTERP_KERNEL::Exception(oss.str());
6938         }
6939     }
6940   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6941   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6942   int offset=(*it)->getNumberOfNodes();
6943   (*it++)->setCoords(res);
6944   for(;it!=meshes.end();it++)
6945     {
6946       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6947       (*it)->setCoords(res);
6948       (*it)->shiftNodeNumbersInConn(offset);
6949       offset+=oldNumberOfNodes;
6950     }
6951 }
6952
6953 /*!
6954  * Merges nodes coincident with a given precision within all given meshes that share
6955  * the nodal connectivity array. The given meshes **can be of different** mesh
6956  * dimension. This method is particularly useful in MEDLoader context to build a \ref
6957  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6958  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6959  *  \param [in,out] meshes - a vector of meshes to update.
6960  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6961  *  \throw If any of \a meshes is NULL.
6962  *  \throw If the \a meshes do not share the same node coordinates array.
6963  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6964  */
6965 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6966 {
6967   if(meshes.empty())
6968     return ;
6969   std::set<const DataArrayDouble *> s;
6970   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6971     {
6972       if(*it)
6973         s.insert((*it)->getCoords());
6974       else
6975         {
6976           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 !";
6977           throw INTERP_KERNEL::Exception(oss.str());
6978         }
6979     }
6980   if(s.size()!=1)
6981     {
6982       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 !";
6983       throw INTERP_KERNEL::Exception(oss.str());
6984     }
6985   const DataArrayDouble *coo=*(s.begin());
6986   if(!coo)
6987     return;
6988   //
6989   DataArrayInt *comm,*commI;
6990   coo->findCommonTuples(eps,-1,comm,commI);
6991   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6992   int oldNbOfNodes=coo->getNumberOfTuples();
6993   int newNbOfNodes;
6994   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6995   if(oldNbOfNodes==newNbOfNodes)
6996     return ;
6997   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6998   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6999     {
7000       (*it)->renumberNodesInConn(o2n->begin());
7001       (*it)->setCoords(newCoords);
7002     } 
7003 }
7004
7005
7006 /*!
7007  * This static operates only for coords in 3D. The polygon is specified by its connectivity nodes in [ \a begin , \a end ).
7008  */
7009 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7010 {
7011   std::size_t i, ip1;
7012   double v[3]={0.,0.,0.};
7013   std::size_t sz=std::distance(begin,end);
7014   if(isQuadratic)
7015     sz/=2;
7016   for(i=0;i<sz;i++)
7017     {
7018       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];
7019       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7020       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7021     }
7022   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7023
7024   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
7025   // SEG3 forming a circle):
7026   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
7027     {
7028       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
7029       for(std::size_t j=0;j<sz;j++)
7030         {
7031           if (j%2)  // current point i is quadratic, next point i+1 is standard
7032             {
7033               i = sz+j;
7034               ip1 = (j+1)%sz; // ip1 = "i+1"
7035             }
7036           else      // current point i is standard, next point i+1 is quadratic
7037             {
7038               i = j;
7039               ip1 = j+sz;
7040             }
7041           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7042           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7043           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7044         }
7045       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7046     }
7047   return (ret>0.);
7048 }
7049
7050 /*!
7051  * The polyhedron is specified by its connectivity nodes in [ \a begin , \a end ).
7052  */
7053 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7054 {
7055   std::vector<std::pair<int,int> > edges;
7056   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7057   const int *bgFace=begin;
7058   for(std::size_t i=0;i<nbOfFaces;i++)
7059     {
7060       const int *endFace=std::find(bgFace+1,end,-1);
7061       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7062       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7063         {
7064           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7065           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7066             return false;
7067           edges.push_back(p1);
7068         }
7069       bgFace=endFace+1;
7070     }
7071   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7072 }
7073
7074 /*!
7075  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7076  */
7077 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7078 {
7079   double vec0[3],vec1[3];
7080   std::size_t sz=std::distance(begin,end);
7081   if(sz%2!=0)
7082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7083   int nbOfNodes=(int)sz/2;
7084   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7085   const double *pt0=coords+3*begin[0];
7086   const double *pt1=coords+3*begin[nbOfNodes];
7087   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7088   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7089 }
7090
7091 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7092 {
7093   std::size_t sz=std::distance(begin,end);
7094   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7095   std::size_t nbOfNodes(sz/2);
7096   std::copy(begin,end,(int *)tmp);
7097   for(std::size_t j=1;j<nbOfNodes;j++)
7098     {
7099       begin[j]=tmp[nbOfNodes-j];
7100       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7101     }
7102 }
7103
7104 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7105 {
7106   std::size_t sz=std::distance(begin,end);
7107   if(sz!=4)
7108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
7109   double vec0[3],vec1[3];
7110   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7111   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]; 
7112   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;
7113 }
7114
7115 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7116 {
7117   std::size_t sz=std::distance(begin,end);
7118   if(sz!=5)
7119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
7120   double vec0[3];
7121   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7122   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7123   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7124 }
7125
7126 /*!
7127  * 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 ) 
7128  * 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
7129  * a 2D space.
7130  *
7131  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7132  * \param [in] coords the coordinates with nb of components exactly equal to 3
7133  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7134  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7135  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7136  */
7137 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, int index, DataArrayInt *res, MEDCouplingUMesh *faces,
7138                                               DataArrayInt *E_Fi, DataArrayInt *E_F, DataArrayInt *F_Ei, DataArrayInt *F_E)
7139 {
7140   int nbFaces = E_Fi->getIJ(index + 1, 0) - E_Fi->getIJ(index, 0);
7141   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7142   double *vPtr=v->getPointer();
7143   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,2);
7144   double *pPtr=p->getPointer();
7145   int *e_fi = E_Fi->getPointer(), *e_f = E_F->getPointer(), *f_ei = F_Ei->getPointer(), *f_e = F_E->getPointer();
7146   const int *f_idx = faces->getNodalConnectivityIndex()->getPointer(), *f_cnn = faces->getNodalConnectivity()->getPointer();
7147   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7148     {
7149       int face = e_f[e_fi[index] + i];
7150       ComputeVecAndPtOfFace(eps, coords->begin(), f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1], vPtr, pPtr);
7151       // to differentiate faces going to different cells:
7152       pPtr++, *pPtr = 0;
7153       for (int j = f_ei[face]; j < f_ei[face + 1]; j++)
7154         *pPtr += f_e[j];
7155     }
7156   pPtr=p->getPointer(); vPtr=v->getPointer();
7157   DataArrayInt *comm1=0,*commI1=0;
7158   v->findCommonTuples(eps,-1,comm1,commI1);
7159   for (int i = 0; i < nbFaces; i++)
7160     if (comm1->findIdFirstEqual(i) < 0)
7161       {
7162         comm1->pushBackSilent(i);
7163         commI1->pushBackSilent(comm1->getNumberOfTuples());
7164       }
7165   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7166   const int *comm1Ptr=comm1->begin();
7167   const int *commI1Ptr=commI1->begin();
7168   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7169   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7170   //
7171   for(int i=0;i<nbOfGrps1;i++)
7172     {
7173       int vecId=comm1Ptr[commI1Ptr[i]];
7174       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7175       DataArrayInt *comm2=0,*commI2=0;
7176       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7177       for (int j = 0; j < commI1Ptr[i+1] - commI1Ptr[i]; j++)
7178         if (comm2->findIdFirstEqual(j) < 0)
7179           {
7180             comm2->pushBackSilent(j);
7181             commI2->pushBackSilent(comm2->getNumberOfTuples());
7182           }
7183       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7184       const int *comm2Ptr=comm2->begin();
7185       const int *commI2Ptr=commI2->begin();
7186       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7187       for(int j=0;j<nbOfGrps2;j++)
7188         {
7189           if(commI2Ptr[j+1] == commI2Ptr[j] + 1)
7190             {
7191               int face = e_f[e_fi[index] + comm1Ptr[commI1Ptr[i] + comm2Ptr[commI2Ptr[j]]]]; //hmmm
7192               res->insertAtTheEnd(f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1]);
7193               res->pushBackSilent(-1);
7194             }
7195           else
7196             {
7197               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7198               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7199               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7200               ids2->transformWithIndArr(e_f + e_fi[index], e_f + e_fi[index + 1]);
7201               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(faces->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7202               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7203               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7204               const int *idsNodePtr=idsNode->begin();
7205               double center[3]; center[0]=pPtr[2*pointId]*vPtr[3*vecId]; center[1]=pPtr[2*pointId]*vPtr[3*vecId+1]; center[2]=pPtr[2*pointId]*vPtr[3*vecId+2];
7206               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7207               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7208               if(std::abs(norm)>eps)
7209                 {
7210                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7211                   mm3->rotate(center,vec,angle);
7212                 }
7213               mm3->changeSpaceDimension(2);
7214               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7215               const int *conn4=mm4->getNodalConnectivity()->begin();
7216               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7217               int nbOfCells=mm4->getNumberOfCells();
7218               for(int k=0;k<nbOfCells;k++)
7219                 {
7220                   int l=0;
7221                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7222                     res->pushBackSilent(idsNodePtr[*work]);
7223                   res->pushBackSilent(-1);
7224                 }
7225             }
7226         }
7227     }
7228   res->popBackSilent();
7229 }
7230
7231 /*!
7232  * 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
7233  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7234  * 
7235  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7236  * \param [in] coords coordinates expected to have 3 components.
7237  * \param [in] begin start of the nodal connectivity of the face.
7238  * \param [in] end end of the nodal connectivity (excluded) of the face.
7239  * \param [out] v the normalized vector of size 3
7240  * \param [out] p the pos of plane
7241  */
7242 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7243 {
7244   std::size_t nbPoints=std::distance(begin,end);
7245   if(nbPoints<3)
7246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7247   double vec[3]={0.,0.,0.};
7248   std::size_t j=0;
7249   bool refFound=false;
7250   for(;j<nbPoints-1 && !refFound;j++)
7251     {
7252       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7253       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7254       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7255       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7256       if(norm>eps)
7257         {
7258           refFound=true;
7259           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7260         }
7261     }
7262   for(std::size_t i=j;i<nbPoints-1;i++)
7263     {
7264       double curVec[3];
7265       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7266       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7267       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7268       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7269       if(norm<eps)
7270         continue;
7271       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7272       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];
7273       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7274       if(norm>eps)
7275         {
7276           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7277           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7278           return ;
7279         }
7280     }
7281   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7282 }
7283
7284 /*!
7285  * This method tries to obtain a well oriented polyhedron.
7286  * If the algorithm fails, an exception will be thrown.
7287  */
7288 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7289 {
7290   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7291   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7292   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7293   isPerm[0]=true;
7294   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7295   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7296   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7297   //
7298   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7299     {
7300       bgFace=begin;
7301       std::size_t smthChanged=0;
7302       for(std::size_t i=0;i<nbOfFaces;i++)
7303         {
7304           endFace=std::find(bgFace+1,end,-1);
7305           nbOfEdgesInFace=std::distance(bgFace,endFace);
7306           if(!isPerm[i])
7307             {
7308               bool b;
7309               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7310                 {
7311                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7312                   std::pair<int,int> p2(p1.second,p1.first);
7313                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7314                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7315                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7316                 }
7317               if(isPerm[i])
7318                 { 
7319                   if(!b)
7320                     std::reverse(bgFace+1,endFace);
7321                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7322                     {
7323                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7324                       std::pair<int,int> p2(p1.second,p1.first);
7325                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7326                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7327                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7328                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7329                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7330                       if(it!=edgesOK.end())
7331                         {
7332                           edgesOK.erase(it);
7333                           edgesFinished.push_back(p1);
7334                         }
7335                       else
7336                         edgesOK.push_back(p1);
7337                     }
7338                 }
7339             }
7340           bgFace=endFace+1;
7341         }
7342       if(smthChanged==0)
7343         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7344     }
7345   if(!edgesOK.empty())
7346     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7347   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7348     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7349       bgFace=begin;
7350       for(std::size_t i=0;i<nbOfFaces;i++)
7351         {
7352           endFace=std::find(bgFace+1,end,-1);
7353           std::reverse(bgFace+1,endFace);
7354           bgFace=endFace+1;
7355         }
7356     }
7357 }
7358
7359
7360 /*!
7361  * This method makes the assumption spacedimension == meshdimension == 2.
7362  * This method works only for linear cells.
7363  * 
7364  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7365  */
7366 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7367 {
7368   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7370   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7371   int oldNbOfNodes(skin->getNumberOfNodes());
7372   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7373   int nbOfNodesExpected(skin->getNumberOfNodes());
7374   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7375   int nbCells(skin->getNumberOfCells());
7376   if(nbCells==nbOfNodesExpected)
7377     return buildUnionOf2DMeshLinear(skin,n2o);
7378   else if(2*nbCells==nbOfNodesExpected)
7379     return buildUnionOf2DMeshQuadratic(skin,n2o);
7380   else
7381     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7382 }
7383
7384 /*!
7385  * This method makes the assumption spacedimension == meshdimension == 3.
7386  * This method works only for linear cells.
7387  * 
7388  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7389  */
7390 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7391 {
7392   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7393     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7394   MCAuto<MEDCouplingUMesh> m=computeSkin();
7395   const int *conn=m->getNodalConnectivity()->begin();
7396   const int *connI=m->getNodalConnectivityIndex()->begin();
7397   int nbOfCells=m->getNumberOfCells();
7398   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7399   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7400   if(nbOfCells<1)
7401     return ret.retn();
7402   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7403   for(int i=1;i<nbOfCells;i++)
7404     {
7405       *work++=-1;
7406       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7407     }
7408   return ret.retn();
7409 }
7410
7411 /*!
7412  * \brief Creates a graph of cell neighbors
7413  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7414  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7415  *  For example
7416  *  - index:  0 3 5 6 6
7417  *  - value:  1 2 3 2 3 3
7418  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7419  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7420  */
7421 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7422 {
7423   checkConnectivityFullyDefined();
7424
7425   int meshDim = this->getMeshDimension();
7426   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7427   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7428   this->getReverseNodalConnectivity(revConn,indexr);
7429   const int* indexr_ptr=indexr->begin();
7430   const int* revConn_ptr=revConn->begin();
7431
7432   const MEDCoupling::DataArrayInt* index;
7433   const MEDCoupling::DataArrayInt* conn;
7434   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7435   index=this->getNodalConnectivityIndex();
7436   int nbCells=this->getNumberOfCells();
7437   const int* index_ptr=index->begin();
7438   const int* conn_ptr=conn->begin();
7439
7440   //creating graph arcs (cell to cell relations)
7441   //arcs are stored in terms of (index,value) notation
7442   // 0 3 5 6 6
7443   // 1 2 3 2 3 3
7444   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7445   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7446
7447   //warning here one node have less than or equal effective number of cell with it
7448   //but cell could have more than effective nodes
7449   //because other equals nodes in other domain (with other global inode)
7450   std::vector <int> cell2cell_index(nbCells+1,0);
7451   std::vector <int> cell2cell;
7452   cell2cell.reserve(3*nbCells);
7453
7454   for (int icell=0; icell<nbCells;icell++)
7455     {
7456       std::map<int,int > counter;
7457       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7458         {
7459           int inode=conn_ptr[iconn];
7460           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7461             {
7462               int icell2=revConn_ptr[iconnr];
7463               std::map<int,int>::iterator iter=counter.find(icell2);
7464               if (iter!=counter.end()) (iter->second)++;
7465               else counter.insert(std::make_pair(icell2,1));
7466             }
7467         }
7468       for (std::map<int,int>::const_iterator iter=counter.begin();
7469            iter!=counter.end(); iter++)
7470         if (iter->second >= meshDim)
7471           {
7472             cell2cell_index[icell+1]++;
7473             cell2cell.push_back(iter->first);
7474           }
7475     }
7476   indexr->decrRef();
7477   revConn->decrRef();
7478   cell2cell_index[0]=0;
7479   for (int icell=0; icell<nbCells;icell++)
7480     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7481
7482   //filling up index and value to create skylinearray structure
7483   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7484   return array;
7485 }
7486
7487
7488 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7489 {
7490   int nbOfCells=getNumberOfCells();
7491   if(nbOfCells<=0)
7492     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7493   ofs << "  <" << getVTKDataSetType() << ">\n";
7494   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7495   ofs << "      <PointData>\n" << pointData << std::endl;
7496   ofs << "      </PointData>\n";
7497   ofs << "      <CellData>\n" << cellData << std::endl;
7498   ofs << "      </CellData>\n";
7499   ofs << "      <Points>\n";
7500   if(getSpaceDimension()==3)
7501     _coords->writeVTK(ofs,8,"Points",byteData);
7502   else
7503     {
7504       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7505       coo->writeVTK(ofs,8,"Points",byteData);
7506     }
7507   ofs << "      </Points>\n";
7508   ofs << "      <Cells>\n";
7509   const int *cPtr=_nodal_connec->begin();
7510   const int *cIPtr=_nodal_connec_index->begin();
7511   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7512   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7513   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7514   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7515   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7516   int szFaceOffsets=0,szConn=0;
7517   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7518     {
7519       *w2=cPtr[cIPtr[i]];
7520       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7521         {
7522           *w1=-1;
7523           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7524           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7525         }
7526       else
7527         {
7528           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7529           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7530           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7531           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7532           w4=std::copy(c.begin(),c.end(),w4);
7533         }
7534     }
7535   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7536   types->writeVTK(ofs,8,"UInt8","types",byteData);
7537   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7538   if(szFaceOffsets!=0)
7539     {//presence of Polyhedra
7540       connectivity->reAlloc(szConn);
7541       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7542       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7543       w1=faces->getPointer();
7544       for(int i=0;i<nbOfCells;i++)
7545         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7546           {
7547             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7548             *w1++=nbFaces;
7549             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7550             for(int j=0;j<nbFaces;j++)
7551               {
7552                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7553                 *w1++=(int)std::distance(w6,w5);
7554                 w1=std::copy(w6,w5,w1);
7555                 w6=w5+1;
7556               }
7557           }
7558       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7559     }
7560   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7561   ofs << "      </Cells>\n";
7562   ofs << "    </Piece>\n";
7563   ofs << "  </" << getVTKDataSetType() << ">\n";
7564 }
7565
7566 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7567 {
7568   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7569   if(_mesh_dim==-2)
7570     { stream << " Not set !"; return ; }
7571   stream << " Mesh dimension : " << _mesh_dim << ".";
7572   if(_mesh_dim==-1)
7573     return ;
7574   if(!_coords)
7575     { stream << " No coordinates set !"; return ; }
7576   if(!_coords->isAllocated())
7577     { stream << " Coordinates set but not allocated !"; return ; }
7578   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7579   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7580   if(!_nodal_connec_index)
7581     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7582   if(!_nodal_connec_index->isAllocated())
7583     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7584   int lgth=_nodal_connec_index->getNumberOfTuples();
7585   int cpt=_nodal_connec_index->getNumberOfComponents();
7586   if(cpt!=1 || lgth<1)
7587     return ;
7588   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7589 }
7590
7591 std::string MEDCouplingUMesh::getVTKDataSetType() const
7592 {
7593   return std::string("UnstructuredGrid");
7594 }
7595
7596 std::string MEDCouplingUMesh::getVTKFileExtension() const
7597 {
7598   return std::string("vtu");
7599 }
7600
7601
7602
7603 /**
7604  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7605  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7606  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7607  * The caller is to deal with the resulting DataArrayInt.
7608  *  \throw If the coordinate array is not set.
7609  *  \throw If the nodal connectivity of the cells is not defined.
7610  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7611  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7612  *
7613  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7614  */
7615 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7616 {
7617   checkFullyDefined();
7618   if(getMeshDimension()!=1)
7619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7620
7621   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7622   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7623   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7624   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7625   const int *d(_d->begin()), *dI(_dI->begin());
7626   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7627   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7628   const int * dsi(_dsi->begin());
7629   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7630   m_points=0;
7631   if (dsii->getNumberOfTuples())
7632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7633
7634   int nc(getNumberOfCells());
7635   MCAuto<DataArrayInt> result(DataArrayInt::New());
7636   result->alloc(nc,1);
7637
7638   // set of edges not used so far
7639   std::set<int> edgeSet;
7640   for (int i=0; i<nc; edgeSet.insert(i), i++);
7641
7642   int startSeg=0;
7643   int newIdx=0;
7644   // while we have points with only one neighbor segments
7645   do
7646     {
7647       std::list<int> linePiece;
7648       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7649       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7650         {
7651           // Fill the list forward (resp. backward) from the start segment:
7652           int activeSeg = startSeg;
7653           int prevPointId = -20;
7654           int ptId;
7655           while (!edgeSet.empty())
7656             {
7657               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7658                 {
7659                   if (direction==0)
7660                     linePiece.push_back(activeSeg);
7661                   else
7662                     linePiece.push_front(activeSeg);
7663                   edgeSet.erase(activeSeg);
7664                 }
7665
7666               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7667               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7668               if (dsi[ptId] == 1) // hitting the end of the line
7669                 break;
7670               prevPointId = ptId;
7671               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7672               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7673             }
7674         }
7675       // Done, save final piece into DA:
7676       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7677       newIdx += linePiece.size();
7678
7679       // identify next valid start segment (one which is not consumed)
7680       if(!edgeSet.empty())
7681         startSeg = *(edgeSet.begin());
7682     }
7683   while (!edgeSet.empty());
7684   return result.retn();
7685 }
7686
7687 /**
7688  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7689  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7690  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7691  * a minimal creation of new nodes is wanted.
7692  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7693  * nodes if a SEG3 is split without information of middle.
7694  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7695  * avoid to have a non conform mesh.
7696  *
7697  * \return int - the number of new nodes created (in most of cases 0).
7698  * 
7699  * \throw If \a this is not coherent.
7700  * \throw If \a this has not spaceDim equal to 2.
7701  * \throw If \a this has not meshDim equal to 2.
7702  * \throw If some subcells needed to be split are orphan.
7703  * \sa MEDCouplingUMesh::conformize2D
7704  */
7705 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7706 {
7707   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7708     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7709   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7710   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7712   if(midOpt==0 && midOptI==0)
7713     {
7714       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7715       return 0;
7716     }
7717   else if(midOpt!=0 && midOptI!=0)
7718     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7719   else
7720     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7721 }
7722
7723 /*!
7724  * 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
7725  * 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
7726  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7727  * 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
7728  * 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.
7729  * 
7730  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7731  */
7732 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7733 {
7734   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7735   if(sz>=4)
7736     {
7737       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7738       if(cm.getDimension()==2)
7739         {
7740           const int *node=nodalConnBg+1;
7741           int startNode=*node++;
7742           double refX=coords[2*startNode];
7743           for(;node!=nodalConnEnd;node++)
7744             {
7745               if(coords[2*(*node)]<refX)
7746                 {
7747                   startNode=*node;
7748                   refX=coords[2*startNode];
7749                 }
7750             }
7751           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7752           refX=1e300;
7753           double tmp1;
7754           double tmp2[2];
7755           double angle0=-M_PI/2;
7756           //
7757           int nextNode=-1;
7758           int prevNode=-1;
7759           double resRef;
7760           double angleNext=0.;
7761           while(nextNode!=startNode)
7762             {
7763               nextNode=-1;
7764               resRef=1e300;
7765               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7766                 {
7767                   if(*node!=tmpOut.back() && *node!=prevNode)
7768                     {
7769                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7770                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7771                       double res;
7772                       if(angleM<=angle0)
7773                         res=angle0-angleM;
7774                       else
7775                         res=angle0-angleM+2.*M_PI;
7776                       if(res<resRef)
7777                         {
7778                           nextNode=*node;
7779                           resRef=res;
7780                           angleNext=angleM;
7781                         }
7782                     }
7783                 }
7784               if(nextNode!=startNode)
7785                 {
7786                   angle0=angleNext-M_PI;
7787                   if(angle0<-M_PI)
7788                     angle0+=2*M_PI;
7789                   prevNode=tmpOut.back();
7790                   tmpOut.push_back(nextNode);
7791                 }
7792             }
7793           std::vector<int> tmp3(2*(sz-1));
7794           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7795           std::copy(nodalConnBg+1,nodalConnEnd,it);
7796           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7797             {
7798               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7799               return false;
7800             }
7801           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7802             {
7803               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7804               return false;
7805             }
7806           else
7807             {
7808               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7809               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7810               return true;
7811             }
7812         }
7813       else
7814         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7815     }
7816   else
7817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7818 }
7819
7820 /*!
7821  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7822  * 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.
7823  * 
7824  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7825  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7826  * \param [in,out] arr array in which the remove operation will be done.
7827  * \param [in,out] arrIndx array in the remove operation will modify
7828  * \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])
7829  * \return true if \b arr and \b arrIndx have been modified, false if not.
7830  */
7831 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7832 {
7833   if(!arrIndx || !arr)
7834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7835   if(offsetForRemoval<0)
7836     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7837   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7838   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7839   int *arrIPtr=arrIndx->getPointer();
7840   *arrIPtr++=0;
7841   int previousArrI=0;
7842   const int *arrPtr=arr->begin();
7843   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7844   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7845     {
7846       if(*arrIPtr-previousArrI>offsetForRemoval)
7847         {
7848           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7849             {
7850               if(s.find(*work)==s.end())
7851                 arrOut.push_back(*work);
7852             }
7853         }
7854       previousArrI=*arrIPtr;
7855       *arrIPtr=(int)arrOut.size();
7856     }
7857   if(arr->getNumberOfTuples()==arrOut.size())
7858     return false;
7859   arr->alloc((int)arrOut.size(),1);
7860   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7861   return true;
7862 }
7863
7864 /*!
7865  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7866  * (\ref numbering-indirect).
7867  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7868  * The selection of extraction is done standardly in new2old format.
7869  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7870  *
7871  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7872  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7873  * \param [in] arrIn arr origin array from which the extraction will be done.
7874  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7875  * \param [out] arrOut the resulting array
7876  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7877  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7878  */
7879 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7880                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7881 {
7882   if(!arrIn || !arrIndxIn)
7883     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7884   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7885   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7886     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7887   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7888   const int *arrInPtr=arrIn->begin();
7889   const int *arrIndxPtr=arrIndxIn->begin();
7890   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7891   if(nbOfGrps<0)
7892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7893   int maxSizeOfArr=arrIn->getNumberOfTuples();
7894   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7895   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7896   arrIo->alloc((int)(sz+1),1);
7897   const int *idsIt=idsOfSelectBg;
7898   int *work=arrIo->getPointer();
7899   *work++=0;
7900   int lgth=0;
7901   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7902     {
7903       if(*idsIt>=0 && *idsIt<nbOfGrps)
7904         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7905       else
7906         {
7907           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7908           throw INTERP_KERNEL::Exception(oss.str());
7909         }
7910       if(lgth>=work[-1])
7911         *work=lgth;
7912       else
7913         {
7914           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7915           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7916           throw INTERP_KERNEL::Exception(oss.str());
7917         }
7918     }
7919   arro->alloc(lgth,1);
7920   work=arro->getPointer();
7921   idsIt=idsOfSelectBg;
7922   for(std::size_t i=0;i<sz;i++,idsIt++)
7923     {
7924       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7925         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7926       else
7927         {
7928           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7929           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7930           throw INTERP_KERNEL::Exception(oss.str());
7931         }
7932     }
7933   arrOut=arro.retn();
7934   arrIndexOut=arrIo.retn();
7935 }
7936
7937 /*!
7938  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7939  * (\ref numbering-indirect).
7940  * 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 ).
7941  * The selection of extraction is done standardly in new2old format.
7942  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7943  *
7944  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7945  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7946  * \param [in] idsOfSelectStep
7947  * \param [in] arrIn arr origin array from which the extraction will be done.
7948  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7949  * \param [out] arrOut the resulting array
7950  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7951  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7952  */
7953 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7954                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7955 {
7956   if(!arrIn || !arrIndxIn)
7957     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7958   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7959   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7960     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7961   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7962   const int *arrInPtr=arrIn->begin();
7963   const int *arrIndxPtr=arrIndxIn->begin();
7964   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7965   if(nbOfGrps<0)
7966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7967   int maxSizeOfArr=arrIn->getNumberOfTuples();
7968   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7969   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7970   arrIo->alloc((int)(sz+1),1);
7971   int idsIt=idsOfSelectStart;
7972   int *work=arrIo->getPointer();
7973   *work++=0;
7974   int lgth=0;
7975   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7976     {
7977       if(idsIt>=0 && idsIt<nbOfGrps)
7978         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7979       else
7980         {
7981           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7982           throw INTERP_KERNEL::Exception(oss.str());
7983         }
7984       if(lgth>=work[-1])
7985         *work=lgth;
7986       else
7987         {
7988           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7989           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7990           throw INTERP_KERNEL::Exception(oss.str());
7991         }
7992     }
7993   arro->alloc(lgth,1);
7994   work=arro->getPointer();
7995   idsIt=idsOfSelectStart;
7996   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7997     {
7998       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7999         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8000       else
8001         {
8002           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8003           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8004           throw INTERP_KERNEL::Exception(oss.str());
8005         }
8006     }
8007   arrOut=arro.retn();
8008   arrIndexOut=arrIo.retn();
8009 }
8010
8011 /*!
8012  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8013  * 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
8014  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8015  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
8016  *
8017  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8018  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8019  * \param [in] arrIn arr origin array from which the extraction will be done.
8020  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8021  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8022  * \param [in] srcArrIndex index array of \b srcArr
8023  * \param [out] arrOut the resulting array
8024  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8025  * 
8026  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8027  */
8028 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8029                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8030                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8031 {
8032   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8033     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8034   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8035   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8036   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8037   std::vector<bool> v(nbOfTuples,true);
8038   int offset=0;
8039   const int *arrIndxInPtr=arrIndxIn->begin();
8040   const int *srcArrIndexPtr=srcArrIndex->begin();
8041   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8042     {
8043       if(*it>=0 && *it<nbOfTuples)
8044         {
8045           v[*it]=false;
8046           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8047         }
8048       else
8049         {
8050           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8051           throw INTERP_KERNEL::Exception(oss.str());
8052         }
8053     }
8054   srcArrIndexPtr=srcArrIndex->begin();
8055   arrIo->alloc(nbOfTuples+1,1);
8056   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8057   const int *arrInPtr=arrIn->begin();
8058   const int *srcArrPtr=srcArr->begin();
8059   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8060   int *arroPtr=arro->getPointer();
8061   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8062     {
8063       if(v[ii])
8064         {
8065           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8066           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8067         }
8068       else
8069         {
8070           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8071           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8072           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8073         }
8074     }
8075   arrOut=arro.retn();
8076   arrIndexOut=arrIo.retn();
8077 }
8078
8079 /*!
8080  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8081  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
8082  *
8083  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8084  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8085  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8086  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8087  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8088  * \param [in] srcArrIndex index array of \b srcArr
8089  * 
8090  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8091  */
8092 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8093                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8094 {
8095   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8096     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8097   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8098   const int *arrIndxInPtr=arrIndxIn->begin();
8099   const int *srcArrIndexPtr=srcArrIndex->begin();
8100   int *arrInOutPtr=arrInOut->getPointer();
8101   const int *srcArrPtr=srcArr->begin();
8102   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8103     {
8104       if(*it>=0 && *it<nbOfTuples)
8105         {
8106           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8107             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8108           else
8109             {
8110               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] !";
8111               throw INTERP_KERNEL::Exception(oss.str());
8112             }
8113         }
8114       else
8115         {
8116           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8117           throw INTERP_KERNEL::Exception(oss.str());
8118         }
8119     }
8120 }
8121
8122 /*!
8123  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8124  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8125  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
8126  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8127  * A negative value in \b arrIn means that it is ignored.
8128  * 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.
8129  * 
8130  * \param [in] arrIn arr origin array from which the extraction will be done.
8131  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8132  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8133  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8134  */
8135 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8136 {
8137   int seed=0,nbOfDepthPeelingPerformed=0;
8138   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8139 }
8140
8141 /*!
8142  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8143  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8144  * 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]].
8145  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8146  * A negative value in \b arrIn means that it is ignored.
8147  * 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.
8148  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8149  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8150  * \param [in] arrIn arr origin array from which the extraction will be done.
8151  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8152  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8153  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8154  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8155  * \sa MEDCouplingUMesh::partitionBySpreadZone
8156  */
8157 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
8158 {
8159   nbOfDepthPeelingPerformed=0;
8160   if(!arrIndxIn)
8161     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8162   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8163   if(nbOfTuples<=0)
8164     {
8165       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8166       return ret;
8167     }
8168   //
8169   std::vector<bool> fetched(nbOfTuples,false);
8170   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8171 }
8172
8173
8174 /*!
8175  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8176  * 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
8177  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8178  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
8179  *
8180  * \param [in] start begin of set of ids of the input extraction (included)
8181  * \param [in] end end of set of ids of the input extraction (excluded)
8182  * \param [in] step step of the set of ids in range mode.
8183  * \param [in] arrIn arr origin array from which the extraction will be done.
8184  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8185  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8186  * \param [in] srcArrIndex index array of \b srcArr
8187  * \param [out] arrOut the resulting array
8188  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8189  * 
8190  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8191  */
8192 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8193                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8194                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8195 {
8196   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
8198   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8199   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8200   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8201   int offset=0;
8202   const int *arrIndxInPtr=arrIndxIn->begin();
8203   const int *srcArrIndexPtr=srcArrIndex->begin();
8204   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
8205   int it=start;
8206   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8207     {
8208       if(it>=0 && it<nbOfTuples)
8209         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8210       else
8211         {
8212           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8213           throw INTERP_KERNEL::Exception(oss.str());
8214         }
8215     }
8216   srcArrIndexPtr=srcArrIndex->begin();
8217   arrIo->alloc(nbOfTuples+1,1);
8218   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8219   const int *arrInPtr=arrIn->begin();
8220   const int *srcArrPtr=srcArr->begin();
8221   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8222   int *arroPtr=arro->getPointer();
8223   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8224     {
8225       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8226       if(pos<0)
8227         {
8228           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8229           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8230         }
8231       else
8232         {
8233           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8234           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8235         }
8236     }
8237   arrOut=arro.retn();
8238   arrIndexOut=arrIo.retn();
8239 }
8240
8241 /*!
8242  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8243  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
8244  *
8245  * \param [in] start begin of set of ids of the input extraction (included)
8246  * \param [in] end end of set of ids of the input extraction (excluded)
8247  * \param [in] step step of the set of ids in range mode.
8248  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8249  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8250  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8251  * \param [in] srcArrIndex index array of \b srcArr
8252  * 
8253  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8254  */
8255 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8256                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8257 {
8258   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8259     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8260   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8261   const int *arrIndxInPtr=arrIndxIn->begin();
8262   const int *srcArrIndexPtr=srcArrIndex->begin();
8263   int *arrInOutPtr=arrInOut->getPointer();
8264   const int *srcArrPtr=srcArr->begin();
8265   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8266   int it=start;
8267   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8268     {
8269       if(it>=0 && it<nbOfTuples)
8270         {
8271           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8272             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8273           else
8274             {
8275               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8276               throw INTERP_KERNEL::Exception(oss.str());
8277             }
8278         }
8279       else
8280         {
8281           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8282           throw INTERP_KERNEL::Exception(oss.str());
8283         }
8284     }
8285 }
8286
8287 /*!
8288  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8289  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8290  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8291  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8292  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8293  * 
8294  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8295  */
8296 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8297 {
8298   checkFullyDefined();
8299   int mdim=getMeshDimension();
8300   int spaceDim=getSpaceDimension();
8301   if(mdim!=spaceDim)
8302     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8303   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8304   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8305   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8306   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8307   ret->setCoords(getCoords());
8308   ret->allocateCells((int)partition.size());
8309   //
8310   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8311     {
8312       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8313       MCAuto<DataArrayInt> cell;
8314       switch(mdim)
8315       {
8316         case 2:
8317           cell=tmp->buildUnionOf2DMesh();
8318           break;
8319         case 3:
8320           cell=tmp->buildUnionOf3DMesh();
8321           break;
8322         default:
8323           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8324       }
8325
8326       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8327     }
8328   //
8329   ret->finishInsertingCells();
8330   return ret.retn();
8331 }
8332
8333 /*!
8334  * This method partitions \b this into contiguous zone.
8335  * This method only needs a well defined connectivity. Coordinates are not considered here.
8336  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8337  */
8338 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8339 {
8340   DataArrayInt *neigh=0,*neighI=0;
8341   computeNeighborsOfCells(neigh,neighI);
8342   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8343   return PartitionBySpreadZone(neighAuto,neighIAuto);
8344 }
8345
8346 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8347 {
8348   if(!arrIn || !arrIndxIn)
8349     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8350   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8351   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8352   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8353     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8354   int nbOfCellsCur(nbOfTuples-1);
8355   std::vector<DataArrayInt *> ret;
8356   if(nbOfCellsCur<=0)
8357     return ret;
8358   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8359   std::vector< MCAuto<DataArrayInt> > ret2;
8360   int seed=0;
8361   while(seed<nbOfCellsCur)
8362     {
8363       int nbOfPeelPerformed=0;
8364       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8365       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8366     }
8367   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8368     ret.push_back((*it).retn());
8369   return ret;
8370 }
8371
8372 /*!
8373  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8374  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8375  *
8376  * \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.
8377  * \return a newly allocated DataArrayInt to be managed by the caller.
8378  * \throw In case of \a code has not the right format (typically of size 3*n)
8379  */
8380 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8381 {
8382   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8383   std::size_t nb=code.size()/3;
8384   if(code.size()%3!=0)
8385     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8386   ret->alloc((int)nb,2);
8387   int *retPtr=ret->getPointer();
8388   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8389     {
8390       retPtr[0]=code[3*i+2];
8391       retPtr[1]=code[3*i+2]+code[3*i+1];
8392     }
8393   return ret.retn();
8394 }
8395
8396 /*!
8397  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8398  * All cells in \a this are expected to be linear 3D cells.
8399  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8400  * It leads to an increase to number of cells.
8401  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8402  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8403  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8404  *
8405  * \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.
8406  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8407  * \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. 
8408  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8409  *          an id of old cell producing it. The caller is to delete this array using
8410  *         decrRef() as it is no more needed.
8411  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8412  *
8413  * \warning This method operates on each cells in this independently ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
8414  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8415  * 
8416  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8417  * \throw If \a this is not fully constituted with linear 3D cells.
8418  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8419  */
8420 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8421 {
8422   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8423   checkConnectivityFullyDefined();
8424   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8426   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8427   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8428   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8429   int *retPt(ret->getPointer());
8430   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8431   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8432   const int *oldc(_nodal_connec->begin());
8433   const int *oldci(_nodal_connec_index->begin());
8434   const double *coords(_coords->begin());
8435   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8436     {
8437       std::vector<int> a; std::vector<double> b;
8438       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8439       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8440       const int *aa(&a[0]);
8441       if(!b.empty())
8442         {
8443           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8444             if(*it<0)
8445               *it=(-(*(it))-1+nbNodes);
8446           addPts->insertAtTheEnd(b.begin(),b.end());
8447           nbNodes+=(int)b.size()/3;
8448         }
8449       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8450         newConn->insertAtTheEnd(aa,aa+4);
8451     }
8452   if(!addPts->empty())
8453     {
8454       addPts->rearrange(3);
8455       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8456       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8457       ret0->setCoords(addPts);
8458     }
8459   else
8460     {
8461       nbOfAdditionalPoints=0;
8462       ret0->setCoords(getCoords());
8463     }
8464   ret0->setNodalConnectivity(newConn);
8465   //
8466   ret->computeOffsetsFull();
8467   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8468   return ret0.retn();
8469 }
8470
8471 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8472     _own_cell(true),_cell_id(-1),_nb_cell(0)
8473 {
8474   if(mesh)
8475     {
8476       mesh->incrRef();
8477       _nb_cell=mesh->getNumberOfCells();
8478     }
8479 }
8480
8481 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8482 {
8483   if(_mesh)
8484     _mesh->decrRef();
8485   if(_own_cell)
8486     delete _cell;
8487 }
8488
8489 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8490     _own_cell(false),_cell_id(bg-1),
8491     _nb_cell(end)
8492 {
8493   if(mesh)
8494     mesh->incrRef();
8495 }
8496
8497 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8498 {
8499   _cell_id++;
8500   if(_cell_id<_nb_cell)
8501     {
8502       _cell->next();
8503       return _cell;
8504     }
8505   else
8506     return 0;
8507 }
8508
8509 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8510 {
8511   if(_mesh)
8512     _mesh->incrRef();
8513 }
8514
8515 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8516 {
8517   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8518 }
8519
8520 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8521 {
8522   if(_mesh)
8523     _mesh->decrRef();
8524 }
8525
8526 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8527     _itc(itc),
8528     _bg(bg),_end(end)
8529 {
8530   if(_mesh)
8531     _mesh->incrRef();
8532 }
8533
8534 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8535 {
8536   if(_mesh)
8537     _mesh->decrRef();
8538 }
8539
8540 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8541 {
8542   return _type;
8543 }
8544
8545 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8546 {
8547   return _end-_bg;
8548 }
8549
8550 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8551 {
8552   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8553 }
8554
8555 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8556 {
8557   if(mesh)
8558     {
8559       mesh->incrRef();
8560       _nb_cell=mesh->getNumberOfCells();
8561     }
8562 }
8563
8564 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8565 {
8566   if(_mesh)
8567     _mesh->decrRef();
8568   delete _cell;
8569 }
8570
8571 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8572 {
8573   const int *c=_mesh->getNodalConnectivity()->begin();
8574   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8575   if(_cell_id<_nb_cell)
8576     {
8577       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8578       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8579       int startId=_cell_id;
8580       _cell_id+=nbOfElems;
8581       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8582     }
8583   else
8584     return 0;
8585 }
8586
8587 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8588 {
8589   if(mesh)
8590     {
8591       _conn=mesh->getNodalConnectivity()->getPointer();
8592       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8593     }
8594 }
8595
8596 void MEDCouplingUMeshCell::next()
8597 {
8598   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8599     {
8600       _conn+=_conn_lgth;
8601       _conn_indx++;
8602     }
8603   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8604 }
8605
8606 std::string MEDCouplingUMeshCell::repr() const
8607 {
8608   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8609     {
8610       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8611       oss << " : ";
8612       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8613       return oss.str();
8614     }
8615   else
8616     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8617 }
8618
8619 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8620 {
8621   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8622     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8623   else
8624     return INTERP_KERNEL::NORM_ERROR;
8625 }
8626
8627 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8628 {
8629   lgth=_conn_lgth;
8630   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8631     return _conn;
8632   else
8633     return 0;
8634 }