Salome HOME
4a8344d8cd1f40eefa7d0bcaee385951fc7cc237
[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.hxx"
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   checkConnectivityFullyDefined();
2484   int *conn(getNodalConnectivity()->getPointer());
2485   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2486   int nbOfCells(getNumberOfCells());
2487   for(int i=0;i<nbOfCells;i++)
2488     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2489       {
2490         int& node=conn[iconn];
2491         if(node>=0)//avoid polyhedron separator
2492           {
2493             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2494             if(it!=newNodeNumbersO2N.end())
2495               {
2496                 node=(*it).second;
2497               }
2498             else
2499               {
2500                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2501                 throw INTERP_KERNEL::Exception(oss.str());
2502               }
2503           }
2504       }
2505   _nodal_connec->declareAsNew();
2506   updateTime();
2507 }
2508
2509 /*!
2510  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2511  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2512  * This method is a generalization of shiftNodeNumbersInConn().
2513  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2514  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2515  *         this->getNumberOfNodes(), in "Old to New" mode. 
2516  *         See \ref numbering for more info on renumbering modes.
2517  *  \throw If the nodal connectivity of cells is not defined.
2518  *
2519  *  \if ENABLE_EXAMPLES
2520  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2521  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2522  *  \endif
2523  */
2524 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2525 {
2526   checkConnectivityFullyDefined();
2527   int *conn=getNodalConnectivity()->getPointer();
2528   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2529   int nbOfCells(getNumberOfCells());
2530   for(int i=0;i<nbOfCells;i++)
2531     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2532       {
2533         int& node=conn[iconn];
2534         if(node>=0)//avoid polyhedron separator
2535           {
2536             node=newNodeNumbersO2N[node];
2537           }
2538       }
2539   _nodal_connec->declareAsNew();
2540   updateTime();
2541 }
2542
2543 /*!
2544  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2545  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2546  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2547  * 
2548  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2549  */
2550 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2551 {
2552   checkConnectivityFullyDefined();
2553   int *conn=getNodalConnectivity()->getPointer();
2554   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2555   int nbOfCells=getNumberOfCells();
2556   for(int i=0;i<nbOfCells;i++)
2557     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2558       {
2559         int& node=conn[iconn];
2560         if(node>=0)//avoid polyhedron separator
2561           {
2562             node+=delta;
2563           }
2564       }
2565   _nodal_connec->declareAsNew();
2566   updateTime();
2567 }
2568
2569 /*!
2570  * This method operates a modification of the connectivity in \b this.
2571  * 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.
2572  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2573  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2574  * 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
2575  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2576  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2577  * 
2578  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2579  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2580  * 
2581  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2582  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2583  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2584  */
2585 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2586 {
2587   checkConnectivityFullyDefined();
2588   std::map<int,int> m;
2589   int val=offset;
2590   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2591     m[*work]=val;
2592   int *conn=getNodalConnectivity()->getPointer();
2593   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2594   int nbOfCells=getNumberOfCells();
2595   for(int i=0;i<nbOfCells;i++)
2596     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2597       {
2598         int& node=conn[iconn];
2599         if(node>=0)//avoid polyhedron separator
2600           {
2601             std::map<int,int>::iterator it=m.find(node);
2602             if(it!=m.end())
2603               node=(*it).second;
2604           }
2605       }
2606   updateTime();
2607 }
2608
2609 /*!
2610  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2611  *
2612  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2613  * After the call of this method the number of cells remains the same as before.
2614  *
2615  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2616  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2617  * be strictly in [0;this->getNumberOfCells()).
2618  *
2619  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2620  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2621  * should be contained in[0;this->getNumberOfCells()).
2622  * 
2623  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2624  * \param check
2625  */
2626 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2627 {
2628   checkConnectivityFullyDefined();
2629   int nbCells=getNumberOfCells();
2630   const int *array=old2NewBg;
2631   if(check)
2632     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2633   //
2634   const int *conn=_nodal_connec->getConstPointer();
2635   const int *connI=_nodal_connec_index->getConstPointer();
2636   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2637   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2638   const int *n2oPtr=n2o->begin();
2639   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2640   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2641   newConn->copyStringInfoFrom(*_nodal_connec);
2642   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2643   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2644   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2645   //
2646   int *newC=newConn->getPointer();
2647   int *newCI=newConnI->getPointer();
2648   int loc=0;
2649   newCI[0]=loc;
2650   for(int i=0;i<nbCells;i++)
2651     {
2652       int pos=n2oPtr[i];
2653       int nbOfElts=connI[pos+1]-connI[pos];
2654       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2655       loc+=nbOfElts;
2656       newCI[i+1]=loc;
2657     }
2658   //
2659   setConnectivity(newConn,newConnI);
2660   if(check)
2661     free(const_cast<int *>(array));
2662 }
2663
2664 /*!
2665  * Finds cells whose bounding boxes intersect a given bounding box.
2666  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2667  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2668  *         zMax (if in 3D). 
2669  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2670  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2671  *         extent of the bounding box of cell to produce an addition to this bounding box.
2672  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2673  *         cells. The caller is to delete this array using decrRef() as it is no more
2674  *         needed. 
2675  *  \throw If the coordinates array is not set.
2676  *  \throw If the nodal connectivity of cells is not defined.
2677  *
2678  *  \if ENABLE_EXAMPLES
2679  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2680  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2681  *  \endif
2682  */
2683 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2684 {
2685   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2686   if(getMeshDimension()==-1)
2687     {
2688       elems->pushBackSilent(0);
2689       return elems.retn();
2690     }
2691   int dim=getSpaceDimension();
2692   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2693   const int* conn      = getNodalConnectivity()->getConstPointer();
2694   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2695   const double* coords = getCoords()->getConstPointer();
2696   int nbOfCells=getNumberOfCells();
2697   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2698     {
2699       for (int i=0; i<dim; i++)
2700         {
2701           elem_bb[i*2]=std::numeric_limits<double>::max();
2702           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2703         }
2704
2705       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2706         {
2707           int node= conn[inode];
2708           if(node>=0)//avoid polyhedron separator
2709             {
2710               for (int idim=0; idim<dim; idim++)
2711                 {
2712                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2713                     {
2714                       elem_bb[idim*2] = coords[node*dim+idim] ;
2715                     }
2716                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2717                     {
2718                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2719                     }
2720                 }
2721             }
2722         }
2723       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2724         elems->pushBackSilent(ielem);
2725     }
2726   return elems.retn();
2727 }
2728
2729 /*!
2730  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2731  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2732  * added in 'elems' parameter.
2733  */
2734 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2735 {
2736   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2737   if(getMeshDimension()==-1)
2738     {
2739       elems->pushBackSilent(0);
2740       return elems.retn();
2741     }
2742   int dim=getSpaceDimension();
2743   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2744   const int* conn      = getNodalConnectivity()->getConstPointer();
2745   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2746   const double* coords = getCoords()->getConstPointer();
2747   int nbOfCells=getNumberOfCells();
2748   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2749     {
2750       for (int i=0; i<dim; i++)
2751         {
2752           elem_bb[i*2]=std::numeric_limits<double>::max();
2753           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2754         }
2755
2756       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2757         {
2758           int node= conn[inode];
2759           if(node>=0)//avoid polyhedron separator
2760             {
2761               for (int idim=0; idim<dim; idim++)
2762                 {
2763                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2764                     {
2765                       elem_bb[idim*2] = coords[node*dim+idim] ;
2766                     }
2767                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2768                     {
2769                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2770                     }
2771                 }
2772             }
2773         }
2774       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2775         elems->pushBackSilent(ielem);
2776     }
2777   return elems.retn();
2778 }
2779
2780 /*!
2781  * Returns a type of a cell by its id.
2782  *  \param [in] cellId - the id of the cell of interest.
2783  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2784  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2785  */
2786 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(std::size_t cellId) const
2787 {
2788   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2789   if(cellId<_nodal_connec_index->getNbOfElems()-1)
2790     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2791   else
2792     {
2793       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2794       throw INTERP_KERNEL::Exception(oss.str());
2795     }
2796 }
2797
2798 /*!
2799  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2800  * This method does not throw exception if geometric type \a type is not in \a this.
2801  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2802  * The coordinates array is not considered here.
2803  *
2804  * \param [in] type the geometric type
2805  * \return cell ids in this having geometric type \a type.
2806  */
2807 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2808 {
2809
2810   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2811   ret->alloc(0,1);
2812   checkConnectivityFullyDefined();
2813   int nbCells=getNumberOfCells();
2814   int mdim=getMeshDimension();
2815   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2816   if(mdim!=(int)cm.getDimension())
2817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2818   const int *ptI=_nodal_connec_index->getConstPointer();
2819   const int *pt=_nodal_connec->getConstPointer();
2820   for(int i=0;i<nbCells;i++)
2821     {
2822       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2823         ret->pushBackSilent(i);
2824     }
2825   return ret.retn();
2826 }
2827
2828 /*!
2829  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2830  */
2831 std::size_t MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2832 {
2833   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2834   std::size_t nbOfCells(getNumberOfCells()),ret(0);
2835   for(std::size_t i=0;i<nbOfCells;i++)
2836     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2837       ret++;
2838   return ret;
2839 }
2840
2841 /*!
2842  * Returns the nodal connectivity of a given cell.
2843  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2844  * all returned node ids can be used in getCoordinatesOfNode().
2845  *  \param [in] cellId - an id of the cell of interest.
2846  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2847  *         cleared before the appending.
2848  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2849  */
2850 void MEDCouplingUMesh::getNodeIdsOfCell(std::size_t cellId, std::vector<int>& conn) const
2851 {
2852   const int *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2853   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2854     if(*w>=0)
2855       conn.push_back(*w);
2856 }
2857
2858 std::string MEDCouplingUMesh::simpleRepr() const
2859 {
2860   static const char msg0[]="No coordinates specified !";
2861   std::ostringstream ret;
2862   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2863   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2864   int tmpp1,tmpp2;
2865   double tt=getTime(tmpp1,tmpp2);
2866   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2867   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2868   if(_mesh_dim>=-1)
2869     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2870   else
2871     { ret << " Mesh dimension has not been set or is invalid !"; }
2872   if(_coords!=0)
2873     {
2874       const int spaceDim=getSpaceDimension();
2875       ret << spaceDim << "\nInfo attached on space dimension : ";
2876       for(int i=0;i<spaceDim;i++)
2877         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2878       ret << "\n";
2879     }
2880   else
2881     ret << msg0 << "\n";
2882   ret << "Number of nodes : ";
2883   if(_coords!=0)
2884     ret << getNumberOfNodes() << "\n";
2885   else
2886     ret << msg0 << "\n";
2887   ret << "Number of cells : ";
2888   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2889     ret << getNumberOfCells() << "\n";
2890   else
2891     ret << "No connectivity specified !" << "\n";
2892   ret << "Cell types present : ";
2893   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2894     {
2895       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2896       ret << cm.getRepr() << " ";
2897     }
2898   ret << "\n";
2899   return ret.str();
2900 }
2901
2902 std::string MEDCouplingUMesh::advancedRepr() const
2903 {
2904   std::ostringstream ret;
2905   ret << simpleRepr();
2906   ret << "\nCoordinates array : \n___________________\n\n";
2907   if(_coords)
2908     _coords->reprWithoutNameStream(ret);
2909   else
2910     ret << "No array set !\n";
2911   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2912   reprConnectivityOfThisLL(ret);
2913   return ret.str();
2914 }
2915
2916 /*!
2917  * This method returns a C++ code that is a dump of \a this.
2918  * This method will throw if this is not fully defined.
2919  */
2920 std::string MEDCouplingUMesh::cppRepr() const
2921 {
2922   static const char coordsName[]="coords";
2923   static const char connName[]="conn";
2924   static const char connIName[]="connI";
2925   checkFullyDefined();
2926   std::ostringstream ret; ret << "// coordinates" << std::endl;
2927   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2928   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2929   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2930   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2931   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2932   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2933   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2934   return ret.str();
2935 }
2936
2937 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2938 {
2939   std::ostringstream ret;
2940   reprConnectivityOfThisLL(ret);
2941   return ret.str();
2942 }
2943
2944 /*!
2945  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsibility to deal with.
2946  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2947  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2948  * some algos).
2949  * 
2950  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2951  * 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
2952  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2953  */
2954 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2955 {
2956   int mdim=getMeshDimension();
2957   if(mdim<0)
2958     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2959   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2960   MCAuto<DataArrayInt> tmp1,tmp2;
2961   bool needToCpyCT=true;
2962   if(!_nodal_connec)
2963     {
2964       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2965       needToCpyCT=false;
2966     }
2967   else
2968     {
2969       tmp1=_nodal_connec;
2970       tmp1->incrRef();
2971     }
2972   if(!_nodal_connec_index)
2973     {
2974       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2975       needToCpyCT=false;
2976     }
2977   else
2978     {
2979       tmp2=_nodal_connec_index;
2980       tmp2->incrRef();
2981     }
2982   ret->setConnectivity(tmp1,tmp2,false);
2983   if(needToCpyCT)
2984     ret->_types=_types;
2985   if(!_coords)
2986     {
2987       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2988       ret->setCoords(coords);
2989     }
2990   else
2991     ret->setCoords(_coords);
2992   return ret.retn();
2993 }
2994
2995 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2996 {
2997   const int *ptI=_nodal_connec_index->getConstPointer();
2998   const int *pt=_nodal_connec->getConstPointer();
2999   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3000     return ptI[cellId+1]-ptI[cellId]-1;
3001   else
3002     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3003 }
3004
3005 /*!
3006  * Returns types of cells of the specified part of \a this mesh.
3007  * This method avoids computing sub-mesh explicitly to get its types.
3008  *  \param [in] begin - an array of cell ids of interest.
3009  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3010  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3011  *         describing the cell types. 
3012  *  \throw If the coordinates array is not set.
3013  *  \throw If the nodal connectivity of cells is not defined.
3014  *  \sa getAllGeoTypes()
3015  */
3016 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3017 {
3018   checkFullyDefined();
3019   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3020   const int *conn=_nodal_connec->getConstPointer();
3021   const int *connIndex=_nodal_connec_index->getConstPointer();
3022   for(const int *w=begin;w!=end;w++)
3023     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3024   return ret;
3025 }
3026
3027 /*!
3028  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3029  * Optionally updates
3030  * a set of types of cells constituting \a this mesh. 
3031  * This method is for advanced users having prepared their connectivity before. For
3032  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3033  *  \param [in] conn - the nodal connectivity array. 
3034  *  \param [in] connIndex - the nodal connectivity index array.
3035  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3036  *         mesh is updated.
3037  */
3038 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3039 {
3040   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3041   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3042   if(isComputingTypes)
3043     computeTypes();
3044   declareAsNew();
3045 }
3046
3047 /*!
3048  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3049  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3050  */
3051 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy):MEDCouplingPointSet(other,deepCpy),_mesh_dim(other._mesh_dim),
3052     _nodal_connec(0),_nodal_connec_index(0),
3053     _types(other._types)
3054 {
3055   if(other._nodal_connec)
3056     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCpy);
3057   if(other._nodal_connec_index)
3058     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCpy);
3059 }
3060
3061 MEDCouplingUMesh::~MEDCouplingUMesh()
3062 {
3063   if(_nodal_connec)
3064     _nodal_connec->decrRef();
3065   if(_nodal_connec_index)
3066     _nodal_connec_index->decrRef();
3067 }
3068
3069 /*!
3070  * Recomputes a set of cell types of \a this mesh. For more info see
3071  * \ref MEDCouplingUMeshNodalConnectivity.
3072  */
3073 void MEDCouplingUMesh::computeTypes()
3074 {
3075   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3076 }
3077
3078
3079 /*!
3080  * Returns a number of cells constituting \a this mesh. 
3081  *  \return int - the number of cells in \a this mesh.
3082  *  \throw If the nodal connectivity of cells is not defined.
3083  */
3084 std::size_t MEDCouplingUMesh::getNumberOfCells() const
3085
3086   if(_nodal_connec_index)
3087     return _nodal_connec_index->getNumberOfTuples()-1;
3088   else
3089     if(_mesh_dim==-1)
3090       return 1;
3091     else
3092       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3093 }
3094
3095 /*!
3096  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3097  * mesh. For more info see \ref meshes.
3098  *  \return int - the dimension of \a this mesh.
3099  *  \throw If the mesh dimension is not defined using setMeshDimension().
3100  */
3101 int MEDCouplingUMesh::getMeshDimension() const
3102 {
3103   if(_mesh_dim<-1)
3104     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3105   return _mesh_dim;
3106 }
3107
3108 /*!
3109  * Returns a length of the nodal connectivity array.
3110  * This method is for test reason. Normally the integer returned is not useable by
3111  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3112  *  \return int - the length of the nodal connectivity array.
3113  */
3114 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3115 {
3116   return _nodal_connec->getNbOfElems();
3117 }
3118
3119 /*!
3120  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3121  */
3122 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3123 {
3124   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3125   tinyInfo.push_back(getMeshDimension());
3126   tinyInfo.push_back(getNumberOfCells());
3127   if(_nodal_connec)
3128     tinyInfo.push_back(getNodalConnectivityArrayLen());
3129   else
3130     tinyInfo.push_back(-1);
3131 }
3132
3133 /*!
3134  * First step of unserialization process.
3135  */
3136 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3137 {
3138   return tinyInfo[6]<=0;
3139 }
3140
3141 /*!
3142  * Second step of serialization process.
3143  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3144  * \param a1
3145  * \param a2
3146  * \param littleStrings
3147  */
3148 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3149 {
3150   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3151   if(tinyInfo[5]!=-1)
3152     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3153 }
3154
3155 /*!
3156  * Third and final step of serialization process.
3157  */
3158 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3159 {
3160   MEDCouplingPointSet::serialize(a1,a2);
3161   if(getMeshDimension()>-1)
3162     {
3163       a1=DataArrayInt::New();
3164       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3165       int *ptA1=a1->getPointer();
3166       const int *conn=getNodalConnectivity()->getConstPointer();
3167       const int *index=getNodalConnectivityIndex()->getConstPointer();
3168       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3169       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3170     }
3171   else
3172     a1=0;
3173 }
3174
3175 /*!
3176  * Second and final unserialization process.
3177  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3178  */
3179 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3180 {
3181   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3182   setMeshDimension(tinyInfo[5]);
3183   if(tinyInfo[7]!=-1)
3184     {
3185       // Connectivity
3186       const int *recvBuffer=a1->getConstPointer();
3187       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3188       myConnecIndex->alloc(tinyInfo[6]+1,1);
3189       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3190       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3191       myConnec->alloc(tinyInfo[7],1);
3192       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3193       setConnectivity(myConnec, myConnecIndex);
3194     }
3195 }
3196
3197
3198
3199 /*!
3200  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3201  * mesh.<br>
3202  * For 1D cells, the returned field contains lengths.<br>
3203  * For 2D cells, the returned field contains areas.<br>
3204  * For 3D cells, the returned field contains volumes.
3205  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3206  *         orientation, i.e. the volume is always positive.
3207  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3208  *         and one time . The caller is to delete this field using decrRef() as it is no
3209  *         more needed.
3210  */
3211 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3212 {
3213   std::string name="MeasureOfMesh_";
3214   name+=getName();
3215   int nbelem=getNumberOfCells();
3216   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3217   field->setName(name);
3218   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3219   array->alloc(nbelem,1);
3220   double *area_vol=array->getPointer();
3221   field->setArray(array) ; array=0;
3222   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3223   field->synchronizeTimeWithMesh();
3224   if(getMeshDimension()!=-1)
3225     {
3226       int ipt;
3227       INTERP_KERNEL::NormalizedCellType type;
3228       int dim_space=getSpaceDimension();
3229       const double *coords=getCoords()->getConstPointer();
3230       const int *connec=getNodalConnectivity()->getConstPointer();
3231       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3232       for(int iel=0;iel<nbelem;iel++)
3233         {
3234           ipt=connec_index[iel];
3235           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3236           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);
3237         }
3238       if(isAbs)
3239         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3240     }
3241   else
3242     {
3243       area_vol[0]=std::numeric_limits<double>::max();
3244     }
3245   return field.retn();
3246 }
3247
3248 /*!
3249  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3250  * mesh.<br>
3251  * For 1D cells, the returned array contains lengths.<br>
3252  * For 2D cells, the returned array contains areas.<br>
3253  * For 3D cells, the returned array contains volumes.
3254  * This method avoids building explicitly a part of \a this mesh to perform the work.
3255  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3256  *         orientation, i.e. the volume is always positive.
3257  *  \param [in] begin - an array of cell ids of interest.
3258  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3259  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3260  *          delete this array using decrRef() as it is no more needed.
3261  * 
3262  *  \if ENABLE_EXAMPLES
3263  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3264  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3265  *  \endif
3266  *  \sa getMeasureField()
3267  */
3268 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3269 {
3270   std::string name="PartMeasureOfMesh_";
3271   name+=getName();
3272   int nbelem=(int)std::distance(begin,end);
3273   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3274   array->setName(name);
3275   array->alloc(nbelem,1);
3276   double *area_vol=array->getPointer();
3277   if(getMeshDimension()!=-1)
3278     {
3279       int ipt;
3280       INTERP_KERNEL::NormalizedCellType type;
3281       int dim_space=getSpaceDimension();
3282       const double *coords=getCoords()->getConstPointer();
3283       const int *connec=getNodalConnectivity()->getConstPointer();
3284       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3285       for(const int *iel=begin;iel!=end;iel++)
3286         {
3287           ipt=connec_index[*iel];
3288           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3289           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3290         }
3291       if(isAbs)
3292         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3293     }
3294   else
3295     {
3296       area_vol[0]=std::numeric_limits<double>::max();
3297     }
3298   return array.retn();
3299 }
3300
3301 /*!
3302  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3303  * \a this one. The returned field contains the dual cell volume for each corresponding
3304  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3305  *  the dual mesh in P1 sens of \a this.<br>
3306  * For 1D cells, the returned field contains lengths.<br>
3307  * For 2D cells, the returned field contains areas.<br>
3308  * For 3D cells, the returned field contains volumes.
3309  * This method is useful to check "P1*" conservative interpolators.
3310  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3311  *         orientation, i.e. the volume is always positive.
3312  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3313  *          nodes and one time. The caller is to delete this array using decrRef() as
3314  *          it is no more needed.
3315  */
3316 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3317 {
3318   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3319   std::string name="MeasureOnNodeOfMesh_";
3320   name+=getName();
3321   int nbNodes=getNumberOfNodes();
3322   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3323   double cst=1./((double)getMeshDimension()+1.);
3324   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3325   array->alloc(nbNodes,1);
3326   double *valsToFill=array->getPointer();
3327   std::fill(valsToFill,valsToFill+nbNodes,0.);
3328   const double *values=tmp->getArray()->getConstPointer();
3329   MCAuto<DataArrayInt> da=DataArrayInt::New();
3330   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3331   getReverseNodalConnectivity(da,daInd);
3332   const int *daPtr=da->getConstPointer();
3333   const int *daIPtr=daInd->getConstPointer();
3334   for(int i=0;i<nbNodes;i++)
3335     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3336       valsToFill[i]+=cst*values[*cell];
3337   ret->setMesh(this);
3338   ret->setArray(array);
3339   return ret.retn();
3340 }
3341
3342 /*!
3343  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3344  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3345  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3346  * and are normalized.
3347  * <br> \a this can be either 
3348  * - a  2D mesh in 2D or 3D space or 
3349  * - an 1D mesh in 2D space.
3350  * 
3351  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3352  *          cells and one time. The caller is to delete this field using decrRef() as
3353  *          it is no more needed.
3354  *  \throw If the nodal connectivity of cells is not defined.
3355  *  \throw If the coordinates array is not set.
3356  *  \throw If the mesh dimension is not set.
3357  *  \throw If the mesh and space dimension is not as specified above.
3358  */
3359 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3360 {
3361   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3362     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3363   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3364   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3365   int nbOfCells=getNumberOfCells();
3366   int nbComp=getMeshDimension()+1;
3367   array->alloc(nbOfCells,nbComp);
3368   double *vals=array->getPointer();
3369   const int *connI=_nodal_connec_index->getConstPointer();
3370   const int *conn=_nodal_connec->getConstPointer();
3371   const double *coords=_coords->getConstPointer();
3372   if(getMeshDimension()==2)
3373     {
3374       if(getSpaceDimension()==3)
3375         {
3376           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3377           const double *locPtr=loc->getConstPointer();
3378           for(int i=0;i<nbOfCells;i++,vals+=3)
3379             {
3380               int offset=connI[i];
3381               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3382               double n=INTERP_KERNEL::norm<3>(vals);
3383               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3384             }
3385         }
3386       else
3387         {
3388           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3389           const double *isAbsPtr=isAbs->getArray()->begin();
3390           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3391             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3392         }
3393     }
3394   else//meshdimension==1
3395     {
3396       double tmp[2];
3397       for(int i=0;i<nbOfCells;i++)
3398         {
3399           int offset=connI[i];
3400           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3401           double n=INTERP_KERNEL::norm<2>(tmp);
3402           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3403           *vals++=-tmp[1];
3404           *vals++=tmp[0];
3405         }
3406     }
3407   ret->setArray(array);
3408   ret->setMesh(this);
3409   ret->synchronizeTimeWithSupport();
3410   return ret.retn();
3411 }
3412
3413 /*!
3414  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3415  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3416  * and are normalized.
3417  * <br> \a this can be either 
3418  * - a  2D mesh in 2D or 3D space or 
3419  * - an 1D mesh in 2D space.
3420  * 
3421  * This method avoids building explicitly a part of \a this mesh to perform the work.
3422  *  \param [in] begin - an array of cell ids of interest.
3423  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3424  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3425  *          cells and one time. The caller is to delete this field using decrRef() as
3426  *          it is no more needed.
3427  *  \throw If the nodal connectivity of cells is not defined.
3428  *  \throw If the coordinates array is not set.
3429  *  \throw If the mesh dimension is not set.
3430  *  \throw If the mesh and space dimension is not as specified above.
3431  *  \sa buildOrthogonalField()
3432  *
3433  *  \if ENABLE_EXAMPLES
3434  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3435  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3436  *  \endif
3437  */
3438 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3439 {
3440   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3441     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3442   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3443   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3444   std::size_t nbelems=std::distance(begin,end);
3445   int nbComp=getMeshDimension()+1;
3446   array->alloc((int)nbelems,nbComp);
3447   double *vals=array->getPointer();
3448   const int *connI=_nodal_connec_index->getConstPointer();
3449   const int *conn=_nodal_connec->getConstPointer();
3450   const double *coords=_coords->getConstPointer();
3451   if(getMeshDimension()==2)
3452     {
3453       if(getSpaceDimension()==3)
3454         {
3455           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3456           const double *locPtr=loc->getConstPointer();
3457           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3458             {
3459               int offset=connI[*i];
3460               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3461               double n=INTERP_KERNEL::norm<3>(vals);
3462               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3463             }
3464         }
3465       else
3466         {
3467           for(std::size_t i=0;i<nbelems;i++)
3468             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3469         }
3470     }
3471   else//meshdimension==1
3472     {
3473       double tmp[2];
3474       for(const int *i=begin;i!=end;i++)
3475         {
3476           int offset=connI[*i];
3477           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3478           double n=INTERP_KERNEL::norm<2>(tmp);
3479           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3480           *vals++=-tmp[1];
3481           *vals++=tmp[0];
3482         }
3483     }
3484   ret->setArray(array);
3485   ret->setMesh(this);
3486   ret->synchronizeTimeWithSupport();
3487   return ret.retn();
3488 }
3489
3490 /*!
3491  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3492  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3493  * and are \b not normalized.
3494  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3495  *          cells and one time. The caller is to delete this field using decrRef() as
3496  *          it is no more needed.
3497  *  \throw If the nodal connectivity of cells is not defined.
3498  *  \throw If the coordinates array is not set.
3499  *  \throw If \a this->getMeshDimension() != 1.
3500  *  \throw If \a this mesh includes cells of type other than SEG2.
3501  */
3502 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3503 {
3504   if(getMeshDimension()!=1)
3505     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3506   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3507     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3508   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3509   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3510   int nbOfCells=getNumberOfCells();
3511   int spaceDim=getSpaceDimension();
3512   array->alloc(nbOfCells,spaceDim);
3513   double *pt=array->getPointer();
3514   const double *coo=getCoords()->getConstPointer();
3515   std::vector<int> conn;
3516   conn.reserve(2);
3517   for(int i=0;i<nbOfCells;i++)
3518     {
3519       conn.resize(0);
3520       getNodeIdsOfCell(i,conn);
3521       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3522     }
3523   ret->setArray(array);
3524   ret->setMesh(this);
3525   ret->synchronizeTimeWithSupport();
3526   return ret.retn();
3527 }
3528
3529 /*!
3530  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3531  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3532  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3533  * from. If a result face is shared by two 3D cells, then the face in included twice in
3534  * the result mesh.
3535  *  \param [in] origin - 3 components of a point defining location of the plane.
3536  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3537  *         must be greater than 1e-6.
3538  *  \param [in] eps - half-thickness of the plane.
3539  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3540  *         producing correspondent 2D cells. The caller is to delete this array
3541  *         using decrRef() as it is no more needed.
3542  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3543  *         not share the node coordinates array with \a this mesh. The caller is to
3544  *         delete this mesh using decrRef() as it is no more needed.  
3545  *  \throw If the coordinates array is not set.
3546  *  \throw If the nodal connectivity of cells is not defined.
3547  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3548  *  \throw If magnitude of \a vec is less than 1e-6.
3549  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3550  *  \throw If \a this includes quadratic cells.
3551  */
3552 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3553 {
3554   checkFullyDefined();
3555   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3556     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3557   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3558   if(candidates->empty())
3559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3560   std::vector<int> nodes;
3561   DataArrayInt *cellIds1D=0;
3562   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3563   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3564   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3565   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3566   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3567   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3568   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3569   revDesc2=0; revDescIndx2=0;
3570   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3571   revDesc1=0; revDescIndx1=0;
3572   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3573   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3574   //
3575   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3576   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3577     cut3DCurve[*it]=-1;
3578   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3579   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3580   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3581                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3582                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3583   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3584   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3585   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3586   if(cellIds2->empty())
3587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3588   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3589   ret->setCoords(mDesc1->getCoords());
3590   ret->setConnectivity(conn,connI,true);
3591   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3592   return ret.retn();
3593 }
3594
3595 /*!
3596  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3597 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
3598 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3599 the result mesh.
3600  *  \param [in] origin - 3 components of a point defining location of the plane.
3601  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3602  *         must be greater than 1e-6.
3603  *  \param [in] eps - half-thickness of the plane.
3604  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3605  *         producing correspondent segments. The caller is to delete this array
3606  *         using decrRef() as it is no more needed.
3607  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3608  *         mesh in 3D space. This mesh does not share the node coordinates array with
3609  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3610  *         no more needed. 
3611  *  \throw If the coordinates array is not set.
3612  *  \throw If the nodal connectivity of cells is not defined.
3613  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3614  *  \throw If magnitude of \a vec is less than 1e-6.
3615  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3616  *  \throw If \a this includes quadratic cells.
3617  */
3618 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3619 {
3620   checkFullyDefined();
3621   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3623   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3624   if(candidates->empty())
3625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3626   std::vector<int> nodes;
3627   DataArrayInt *cellIds1D(0);
3628   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3629   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3630   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3631   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3632   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3633   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3634   //
3635   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3636   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3637     cut3DCurve[*it]=-1;
3638   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3639   int ncellsSub=subMesh->getNumberOfCells();
3640   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3641   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3642                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3643                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3644   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3645   conn->alloc(0,1);
3646   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3647   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3648   for(int i=0;i<ncellsSub;i++)
3649     {
3650       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3651         {
3652           if(cut3DSurf[i].first!=-2)
3653             {
3654               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3655               connI->pushBackSilent(conn->getNumberOfTuples());
3656               cellIds2->pushBackSilent(i);
3657             }
3658           else
3659             {
3660               int cellId3DSurf=cut3DSurf[i].second;
3661               int offset=nodalI[cellId3DSurf]+1;
3662               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3663               for(int j=0;j<nbOfEdges;j++)
3664                 {
3665                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3666                   connI->pushBackSilent(conn->getNumberOfTuples());
3667                   cellIds2->pushBackSilent(cellId3DSurf);
3668                 }
3669             }
3670         }
3671     }
3672   if(cellIds2->empty())
3673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3674   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3675   ret->setCoords(mDesc1->getCoords());
3676   ret->setConnectivity(conn,connI,true);
3677   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3678   return ret.retn();
3679 }
3680
3681 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3682 {
3683   checkFullyDefined();
3684   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3686   if(getNumberOfCells()!=1)
3687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3688   //
3689   std::vector<int> nodes;
3690   findNodesOnPlane(origin,vec,eps,nodes);
3691   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());
3692   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3693   revDesc2=0; revDescIndx2=0;
3694   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3695   revDesc1=0; revDescIndx1=0;
3696   DataArrayInt *cellIds1D(0);
3697   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3698   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3699   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3700   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3701     cut3DCurve[*it]=-1;
3702   bool sameNbNodes;
3703   {
3704     int oldNbNodes(mDesc1->getNumberOfNodes());
3705     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3706     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3707   }
3708   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3709   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3710                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3711                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3712   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3713   connI->pushBackSilent(0); conn->alloc(0,1);
3714   {
3715     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3716     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3717     if(cellIds2->empty())
3718       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3719   }
3720   std::vector<std::vector<int> > res;
3721   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3722   std::size_t sz(res.size());
3723   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3725   for(std::size_t i=0;i<sz;i++)
3726     {
3727       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3728       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3729       connI->pushBackSilent(conn->getNumberOfTuples());
3730     }
3731   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3732   ret->setCoords(mDesc1->getCoords());
3733   ret->setConnectivity(conn,connI,true);
3734   int nbCellsRet(ret->getNumberOfCells());
3735   //
3736   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3737   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3738   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3739   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3740   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3741   MCAuto<DataArrayDouble> occm;
3742   {
3743     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3744     occm=DataArrayDouble::Substract(ccm,pt);
3745   }
3746   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3747   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);
3748   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3749   //
3750   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3751   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3752   ret2->setCoords(mDesc1->getCoords());
3753   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3754   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3755   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3756   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3757   if(dott->getIJ(0,0)>0)
3758     {
3759       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3760       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3761     }
3762   else
3763     {
3764       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3765       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3766     }
3767   for(int i=1;i<nbCellsRet;i++)
3768     {
3769       if(dott2->getIJ(i,0)<0)
3770         {
3771           if(ciPtr[i+1]-ciPtr[i]>=4)
3772             {
3773               cell0.push_back(-1);
3774               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3775             }
3776         }
3777       else
3778         {
3779           if(ciPtr[i+1]-ciPtr[i]>=4)
3780             {
3781               cell1.push_back(-1);
3782               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3783             }
3784         }
3785     }
3786   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3787   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3788   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3789   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3790   ret2->setConnectivity(conn2,conn2I,true);
3791   ret2->checkConsistencyLight();
3792   ret2->orientCorrectlyPolyhedrons();
3793   return ret2;
3794 }
3795
3796 /*!
3797  * Finds cells whose bounding boxes intersect a given plane.
3798  *  \param [in] origin - 3 components of a point defining location of the plane.
3799  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3800  *         must be greater than 1e-6.
3801  *  \param [in] eps - half-thickness of the plane.
3802  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3803  *         cells. The caller is to delete this array using decrRef() as it is no more
3804  *         needed.
3805  *  \throw If the coordinates array is not set.
3806  *  \throw If the nodal connectivity of cells is not defined.
3807  *  \throw If \a this->getSpaceDimension() != 3.
3808  *  \throw If magnitude of \a vec is less than 1e-6.
3809  *  \sa buildSlice3D()
3810  */
3811 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3812 {
3813   checkFullyDefined();
3814   if(getSpaceDimension()!=3)
3815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3816   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3817   if(normm<1e-6)
3818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3819   double vec2[3];
3820   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3821   double angle=acos(vec[2]/normm);
3822   MCAuto<DataArrayInt> cellIds;
3823   double bbox[6];
3824   if(angle>eps)
3825     {
3826       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3827       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3828       if(normm2/normm>1e-6)
3829         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3830       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3831       mw->setCoords(coo);
3832       mw->getBoundingBox(bbox);
3833       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3834       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3835     }
3836   else
3837     {
3838       getBoundingBox(bbox);
3839       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3840       cellIds=getCellsInBoundingBox(bbox,eps);
3841     }
3842   return cellIds.retn();
3843 }
3844
3845 /*!
3846  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3847  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3848  * No consideration of coordinate is done by this method.
3849  * 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)
3850  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be useful.
3851  */
3852 bool MEDCouplingUMesh::isContiguous1D() const
3853 {
3854   if(getMeshDimension()!=1)
3855     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3856   int nbCells=getNumberOfCells();
3857   if(nbCells<1)
3858     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3859   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3860   int ref=conn[connI[0]+2];
3861   for(int i=1;i<nbCells;i++)
3862     {
3863       if(conn[connI[i]+1]!=ref)
3864         return false;
3865       ref=conn[connI[i]+2];
3866     }
3867   return true;
3868 }
3869
3870 /*!
3871  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3872  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3873  * \param pt reference point of the line
3874  * \param v normalized director vector of the line
3875  * \param eps max precision before throwing an exception
3876  * \param res output of size this->getNumberOfCells
3877  */
3878 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3879 {
3880   if(getMeshDimension()!=1)
3881     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3882   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3883     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3884   if(getSpaceDimension()!=3)
3885     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3886   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3887   const double *fPtr=f->getArray()->getConstPointer();
3888   double tmp[3];
3889   for(std::size_t i=0;i<getNumberOfCells();i++)
3890     {
3891       const double *tmp1=fPtr+3*i;
3892       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3893       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3894       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3895       double n1=INTERP_KERNEL::norm<3>(tmp);
3896       n1/=INTERP_KERNEL::norm<3>(tmp1);
3897       if(n1>eps)
3898         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3899     }
3900   const double *coo=getCoords()->getConstPointer();
3901   for(int i=0;i<getNumberOfNodes();i++)
3902     {
3903       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3904       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3905       res[i]=std::accumulate(tmp,tmp+3,0.);
3906     }
3907 }
3908
3909 /*!
3910  * 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. 
3911  * \a this is expected to be a mesh so that its space dimension is equal to its
3912  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3913  * 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).
3914  *
3915  * 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
3916  * 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).
3917  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3918  *
3919  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3920  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3921  *
3922  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3923  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3924  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3925  * \return the positive value of the distance.
3926  * \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
3927  * dimension - 1.
3928  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3929  */
3930 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3931 {
3932   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3933   if(meshDim!=spaceDim-1)
3934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3935   if(meshDim!=2 && meshDim!=1)
3936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3937   checkFullyDefined();
3938   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3939     { 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()); }
3940   DataArrayInt *ret1=0;
3941   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3942   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3943   MCAuto<DataArrayInt> ret1Safe(ret1);
3944   cellId=*ret1Safe->begin();
3945   return *ret0->begin();
3946 }
3947
3948 /*!
3949  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3950  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3951  * 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
3952  * 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).
3953  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3954  * 
3955  * \a this is expected to be a mesh so that its space dimension is equal to its
3956  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3957  * 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).
3958  *
3959  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3960  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3961  *
3962  * \param [in] pts the list of points in which each tuple represents a point
3963  * \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.
3964  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3965  * \throw if number of components of \a pts is not equal to the space dimension.
3966  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3967  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3968  */
3969 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3970 {
3971   if(!pts)
3972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3973   pts->checkAllocated();
3974   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3975   if(meshDim!=spaceDim-1)
3976     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3977   if(meshDim!=2 && meshDim!=1)
3978     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3979   if((int)pts->getNumberOfComponents()!=spaceDim)
3980     {
3981       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3982       throw INTERP_KERNEL::Exception(oss.str());
3983     }
3984   checkFullyDefined();
3985   int nbCells=getNumberOfCells();
3986   if(nbCells==0)
3987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3988   int nbOfPts=pts->getNumberOfTuples();
3989   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3990   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3991   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3992   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3993   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3994   const double *bbox(bboxArr->begin());
3995   switch(spaceDim)
3996   {
3997     case 3:
3998       {
3999         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4000         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
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             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4007           }
4008         break;
4009       }
4010     case 2:
4011       {
4012         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4013         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4014           {
4015             double x=std::numeric_limits<double>::max();
4016             std::vector<int> elems;
4017             myTree.getMinDistanceOfMax(ptsPtr,x);
4018             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4019             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4020           }
4021         break;
4022       }
4023     default:
4024       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4025   }
4026   cellIds=ret1.retn();
4027   return ret0.retn();
4028 }
4029
4030 /// @cond INTERNAL
4031
4032 /// @endcond
4033
4034 /*!
4035  * Finds cells in contact with a ball (i.e. a point with precision). 
4036  * 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.
4037  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4038  *
4039  * \warning This method is suitable if the caller intends to evaluate only one
4040  *          point, for more points getCellsContainingPoints() is recommended as it is
4041  *          faster. 
4042  *  \param [in] pos - array of coordinates of the ball central point.
4043  *  \param [in] eps - ball radius.
4044  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4045  *         if there are no such cells.
4046  *  \throw If the coordinates array is not set.
4047  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4048  */
4049 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4050 {
4051   std::vector<int> elts;
4052   getCellsContainingPoint(pos,eps,elts);
4053   if(elts.empty())
4054     return -1;
4055   return elts.front();
4056 }
4057
4058 /*!
4059  * Finds cells in contact with a ball (i.e. a point with precision).
4060  * 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.
4061  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4062  * \warning This method is suitable if the caller intends to evaluate only one
4063  *          point, for more points getCellsContainingPoints() is recommended as it is
4064  *          faster. 
4065  *  \param [in] pos - array of coordinates of the ball central point.
4066  *  \param [in] eps - ball radius.
4067  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4068  *         before inserting ids.
4069  *  \throw If the coordinates array is not set.
4070  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4071  *
4072  *  \if ENABLE_EXAMPLES
4073  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4074  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4075  *  \endif
4076  */
4077 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4078 {
4079   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4080   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4081   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4082 }
4083
4084 void MEDCouplingUMesh::getCellsContainingPointsZeAlg(const double *pos, int nbOfPoints, double eps,
4085                                                      MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex,
4086                                                      std::function<bool(INTERP_KERNEL::NormalizedCellType,int)> sensibilityTo2DQuadraticLinearCellsFunc) const
4087 {
4088   int spaceDim(getSpaceDimension()),mDim(getMeshDimension());
4089   if(spaceDim==3)
4090     {
4091       if(mDim==3)
4092         {
4093           const double *coords=_coords->getConstPointer();
4094           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4095         }
4096       else
4097         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4098     }
4099   else if(spaceDim==2)
4100     {
4101       if(mDim==2)
4102         {
4103           const double *coords=_coords->getConstPointer();
4104           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4105         }
4106       else
4107         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4108     }
4109   else if(spaceDim==1)
4110     {
4111       if(mDim==1)
4112         {
4113           const double *coords=_coords->getConstPointer();
4114           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4115         }
4116       else
4117         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4118     }
4119   else
4120     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4121 }
4122
4123 /*!
4124  * Finds cells in contact with several balls (i.e. points with precision).
4125  * This method is an extension of getCellContainingPoint() and
4126  * getCellsContainingPoint() for the case of multiple points.
4127  * 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.
4128  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4129  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4130  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4131  *         this->getSpaceDimension() * \a nbOfPoints 
4132  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4133  *  \param [in] eps - radius of balls (i.e. the precision).
4134  *  \param [out] elts - vector returning ids of found cells.
4135  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4136  *         dividing cell ids in \a elts into groups each referring to one
4137  *         point. Its every element (except the last one) is an index pointing to the
4138  *         first id of a group of cells. For example cells in contact with the *i*-th
4139  *         point are described by following range of indices:
4140  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4141  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4142  *         Number of cells in contact with the *i*-th point is
4143  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4144  *  \throw If the coordinates array is not set.
4145  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4146  *
4147  *  \if ENABLE_EXAMPLES
4148  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4149  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4150  *  \endif
4151  */
4152 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4153                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4154 {
4155   auto yesImSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType ct, int mdim) { return INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic() && mdim == 2; } );
4156   this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,yesImSensibleTo2DQuadraticLinearCellsFunc);
4157 }
4158
4159 /*!
4160  * Behaves like MEDCouplingMesh::getCellsContainingPoints for cells in \a this that are linear.
4161  * For quadratic cells in \a this, this method behaves by just considering linear part of cells.
4162  * This method is here only for backward compatibility (interpolation GaussPoints to GaussPoints).
4163  * 
4164  * \sa MEDCouplingUMesh::getCellsContainingPoints, MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss
4165  */
4166 void MEDCouplingUMesh::getCellsContainingPointsLinearPartOnlyOnNonDynType(const double *pos, int nbOfPoints, double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4167 {
4168   auto noImNotSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType,int) { return false; } );
4169   this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,noImNotSensibleTo2DQuadraticLinearCellsFunc);
4170 }
4171
4172 /*!
4173  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4174  * least two its edges intersect each other anywhere except their extremities. An
4175  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4176  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4177  *         cleared before filling in.
4178  *  \param [in] eps - precision.
4179  *  \throw If \a this->getMeshDimension() != 2.
4180  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4181  */
4182 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4183 {
4184   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4185   if(getMeshDimension()!=2)
4186     throw INTERP_KERNEL::Exception(msg);
4187   int spaceDim=getSpaceDimension();
4188   if(spaceDim!=2 && spaceDim!=3)
4189     throw INTERP_KERNEL::Exception(msg);
4190   const int *conn=_nodal_connec->getConstPointer();
4191   const int *connI=_nodal_connec_index->getConstPointer();
4192   int nbOfCells=getNumberOfCells();
4193   std::vector<double> cell2DinS2;
4194   for(int i=0;i<nbOfCells;i++)
4195     {
4196       int offset=connI[i];
4197       int nbOfNodesForCell=connI[i+1]-offset-1;
4198       if(nbOfNodesForCell<=3)
4199         continue;
4200       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4201       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4202       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4203         cells.push_back(i);
4204       cell2DinS2.clear();
4205     }
4206 }
4207
4208 /*!
4209  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4210  *
4211  * 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.
4212  * 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.
4213  * 
4214  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4215  * This convex envelop is computed using Jarvis march algorithm.
4216  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4217  * 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)
4218  * 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.
4219  *
4220  * \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.
4221  * \sa MEDCouplingUMesh::colinearize2D
4222  */
4223 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4224 {
4225   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4227   checkFullyDefined();
4228   const double *coords=getCoords()->getConstPointer();
4229   int nbOfCells=getNumberOfCells();
4230   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4231   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4232   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4233   int *workIndexOut=nodalConnecIndexOut->getPointer();
4234   *workIndexOut=0;
4235   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4236   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4237   std::set<INTERP_KERNEL::NormalizedCellType> types;
4238   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4239   isChanged->alloc(0,1);
4240   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4241     {
4242       int pos=nodalConnecOut->getNumberOfTuples();
4243       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4244         isChanged->pushBackSilent(i);
4245       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4246       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4247     }
4248   if(isChanged->empty())
4249     return 0;
4250   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4251   _types=types;
4252   return isChanged.retn();
4253 }
4254
4255 /*!
4256  * This method is \b NOT const because it can modify \a this.
4257  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4258  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4259  * \param policy specifies the type of extrusion chosen:
4260  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4261  *   will be repeated to build each level
4262  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4263  *   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
4264  *   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
4265  *   arc.
4266  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4267  */
4268 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4269 {
4270   checkFullyDefined();
4271   mesh1D->checkFullyDefined();
4272   if(!mesh1D->isContiguous1D())
4273     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4274   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4275     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4276   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4277     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4278   if(mesh1D->getMeshDimension()!=1)
4279     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4280   bool isQuad=false;
4281   if(isPresenceOfQuadratic())
4282     {
4283       if(mesh1D->isFullyQuadratic())
4284         isQuad=true;
4285       else
4286         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4287     }
4288   int oldNbOfNodes(getNumberOfNodes());
4289   MCAuto<DataArrayDouble> newCoords;
4290   switch(policy)
4291   {
4292     case 0:
4293       {
4294         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4295         break;
4296       }
4297     case 1:
4298       {
4299         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4300         break;
4301       }
4302     default:
4303       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4304   }
4305   setCoords(newCoords);
4306   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4307   updateTime();
4308   return ret.retn();
4309 }
4310
4311
4312 /*!
4313  * Checks if \a this mesh is constituted by only quadratic cells.
4314  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4315  *  \throw If the coordinates array is not set.
4316  *  \throw If the nodal connectivity of cells is not defined.
4317  */
4318 bool MEDCouplingUMesh::isFullyQuadratic() const
4319 {
4320   checkFullyDefined();
4321   bool ret=true;
4322   int nbOfCells=getNumberOfCells();
4323   for(int i=0;i<nbOfCells && ret;i++)
4324     {
4325       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4326       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4327       ret=cm.isQuadratic();
4328     }
4329   return ret;
4330 }
4331
4332 /*!
4333  * Checks if \a this mesh includes any quadratic cell.
4334  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4335  *  \throw If the coordinates array is not set.
4336  *  \throw If the nodal connectivity of cells is not defined.
4337  */
4338 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4339 {
4340   checkFullyDefined();
4341   bool ret=false;
4342   int nbOfCells=getNumberOfCells();
4343   for(int i=0;i<nbOfCells && !ret;i++)
4344     {
4345       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4346       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4347       ret=cm.isQuadratic();
4348     }
4349   return ret;
4350 }
4351
4352 /*!
4353  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4354  * this mesh, it remains unchanged.
4355  *  \throw If the coordinates array is not set.
4356  *  \throw If the nodal connectivity of cells is not defined.
4357  */
4358 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4359 {
4360   checkFullyDefined();
4361   int nbOfCells(getNumberOfCells());
4362   int delta=0;
4363   const int *iciptr=_nodal_connec_index->begin();
4364   for(int i=0;i<nbOfCells;i++)
4365     {
4366       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4367       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4368       if(cm.isQuadratic())
4369         {
4370           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4371           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4372           if(!cml.isDynamic())
4373             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4374           else
4375             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4376         }
4377     }
4378   if(delta==0)
4379     return ;
4380   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4381   const int *icptr(_nodal_connec->begin());
4382   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4383   newConnI->alloc(nbOfCells+1,1);
4384   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4385   *ociptr=0;
4386   _types.clear();
4387   for(int i=0;i<nbOfCells;i++,ociptr++)
4388     {
4389       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4390       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4391       if(!cm.isQuadratic())
4392         {
4393           _types.insert(type);
4394           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4395           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4396         }
4397       else
4398         {
4399           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4400           _types.insert(typel);
4401           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4402           int newNbOfNodes=cml.getNumberOfNodes();
4403           if(cml.isDynamic())
4404             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4405           *ocptr++=(int)typel;
4406           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4407           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4408         }
4409     }
4410   setConnectivity(newConn,newConnI,false);
4411 }
4412
4413 /*!
4414  * This method converts all linear cell in \a this to quadratic one.
4415  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4416  * 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)
4417  * 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.
4418  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4419  * end of the existing coordinates.
4420  * 
4421  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4422  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4423  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4424  * 
4425  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4426  *
4427  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4428  */
4429 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4430 {
4431   DataArrayInt *conn=0,*connI=0;
4432   DataArrayDouble *coords=0;
4433   std::set<INTERP_KERNEL::NormalizedCellType> types;
4434   checkFullyDefined();
4435   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4436   MCAuto<DataArrayDouble> coordsSafe;
4437   int meshDim=getMeshDimension();
4438   switch(conversionType)
4439   {
4440     case 0:
4441       switch(meshDim)
4442       {
4443         case 1:
4444           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4445           connSafe=conn; connISafe=connI; coordsSafe=coords;
4446           break;
4447         case 2:
4448           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4449           connSafe=conn; connISafe=connI; coordsSafe=coords;
4450           break;
4451         case 3:
4452           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4453           connSafe=conn; connISafe=connI; coordsSafe=coords;
4454           break;
4455         default:
4456           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4457       }
4458       break;
4459         case 1:
4460           {
4461             switch(meshDim)
4462             {
4463               case 1:
4464                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4465                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4466                 break;
4467               case 2:
4468                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4469                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4470                 break;
4471               case 3:
4472                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4473                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4474                 break;
4475               default:
4476                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4477             }
4478             break;
4479           }
4480         default:
4481           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4482   }
4483   setConnectivity(connSafe,connISafe,false);
4484   _types=types;
4485   setCoords(coordsSafe);
4486   return ret.retn();
4487 }
4488
4489 /*!
4490  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4491  * so that the number of cells remains the same. Quadratic faces are converted to
4492  * polygons. This method works only for 2D meshes in
4493  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4494  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4495  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4496  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4497  *         a polylinized edge constituting the input polygon.
4498  *  \throw If the coordinates array is not set.
4499  *  \throw If the nodal connectivity of cells is not defined.
4500  *  \throw If \a this->getMeshDimension() != 2.
4501  *  \throw If \a this->getSpaceDimension() != 2.
4502  */
4503 void MEDCouplingUMesh::tessellate2D(double eps)
4504 {
4505   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4506   if(spaceDim!=2)
4507     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4508   switch(meshDim)
4509     {
4510     case 1:
4511       return tessellate2DCurveInternal(eps);
4512     case 2:
4513       return tessellate2DInternal(eps);
4514     default:
4515       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4516     }
4517 }
4518 /*!
4519  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4520  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4521  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4522  *         a sub-divided edge.
4523  *  \throw If the coordinates array is not set.
4524  *  \throw If the nodal connectivity of cells is not defined.
4525  *  \throw If \a this->getMeshDimension() != 1.
4526  *  \throw If \a this->getSpaceDimension() != 2.
4527  */
4528
4529 #if 0
4530 /*!
4531  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4532  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4533  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4534  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4535  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4536  * This method can be seen as the opposite method of colinearize2D.
4537  * 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
4538  * to avoid to modify the numbering of existing nodes.
4539  *
4540  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4541  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4542  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4543  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4544  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4545  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4546  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4547  *
4548  * \sa buildDescendingConnectivity2
4549  */
4550 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4551                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4552 {
4553   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4554     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4555   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4556   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4558   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4560   //DataArrayInt *out0(0),*outi0(0);
4561   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4562   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4563   //out0s=out0s->buildUnique(); out0s->sort(true);
4564 }
4565 #endif
4566
4567
4568 /*!
4569  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4570  * In addition, returns an array mapping new cells to old ones. <br>
4571  * This method typically increases the number of cells in \a this mesh
4572  * but the number of nodes remains \b unchanged.
4573  * That's why the 3D splitting policies
4574  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4575  *  \param [in] policy - specifies a pattern used for splitting.
4576  * The semantic of \a policy is:
4577  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4578  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4579  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4580  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4581  *
4582  *
4583  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4584  *          an id of old cell producing it. The caller is to delete this array using
4585  *         decrRef() as it is no more needed.
4586  *
4587  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4588  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4589  *          and \a this->getMeshDimension() != 3. 
4590  *  \throw If \a policy is not one of the four discussed above.
4591  *  \throw If the nodal connectivity of cells is not defined.
4592  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4593  */
4594 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4595 {
4596   switch(policy)
4597   {
4598     case 0:
4599       return simplexizePol0();
4600     case 1:
4601       return simplexizePol1();
4602     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4603         return simplexizePlanarFace5();
4604     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4605         return simplexizePlanarFace6();
4606     default:
4607       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)");
4608   }
4609 }
4610
4611 /*!
4612  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4613  * - 1D: INTERP_KERNEL::NORM_SEG2
4614  * - 2D: INTERP_KERNEL::NORM_TRI3
4615  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4616  *
4617  * This method is useful for users that need to use P1 field services as
4618  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4619  * All these methods need mesh support containing only simplex cells.
4620  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4621  *  \throw If the coordinates array is not set.
4622  *  \throw If the nodal connectivity of cells is not defined.
4623  *  \throw If \a this->getMeshDimension() < 1.
4624  */
4625 bool MEDCouplingUMesh::areOnlySimplexCells() const
4626 {
4627   checkFullyDefined();
4628   int mdim=getMeshDimension();
4629   if(mdim<1 || mdim>3)
4630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4631   int nbCells=getNumberOfCells();
4632   const int *conn=_nodal_connec->begin();
4633   const int *connI=_nodal_connec_index->begin();
4634   for(int i=0;i<nbCells;i++)
4635     {
4636       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4637       if(!cm.isSimplex())
4638         return false;
4639     }
4640   return true;
4641 }
4642
4643
4644
4645 /*!
4646  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4647  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4648  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell.
4649  * Quadratic cells in 2D are also handled. In those cells edges where start=end=midpoint are removed.
4650  * This method does \b not perform geometrical checks and checks only nodal connectivity of cells,
4651  * so it can be useful to call mergeNodes() before calling this method.
4652  *  \throw If \a this->getMeshDimension() <= 1.
4653  *  \throw If the coordinates array is not set.
4654  *  \throw If the nodal connectivity of cells is not defined.
4655  */
4656 void MEDCouplingUMesh::convertDegeneratedCells()
4657 {
4658   checkFullyDefined();
4659   if(getMeshDimension()<=1)
4660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4661   int nbOfCells=getNumberOfCells();
4662   if(nbOfCells<1)
4663     return ;
4664   int initMeshLgth=getNodalConnectivityArrayLen();
4665   int *conn=_nodal_connec->getPointer();
4666   int *index=_nodal_connec_index->getPointer();
4667   int posOfCurCell=0;
4668   int newPos=0;
4669   int lgthOfCurCell;
4670   for(int i=0;i<nbOfCells;i++)
4671     {
4672       lgthOfCurCell=index[i+1]-posOfCurCell;
4673       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4674       int newLgth;
4675       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4676                                                                                                      conn+newPos+1,newLgth);
4677       conn[newPos]=newType;
4678       newPos+=newLgth+1;
4679       posOfCurCell=index[i+1];
4680       index[i+1]=newPos;
4681     }
4682   if(newPos!=initMeshLgth)
4683     _nodal_connec->reAlloc(newPos);
4684   computeTypes();
4685 }
4686
4687 /*!
4688  * Same as MEDCouplingUMesh::convertDegeneratedCells() plus deletion of the flat cells.
4689  * A cell is flat in the following cases:
4690  *   - for a linear cell, all points in the connectivity are equal
4691  *   - for a quadratic cell, either the above, or a quadratic polygon with two (linear) points and two
4692  *   identical quadratic points
4693  * \return a new instance of DataArrayInt holding ids of removed cells. The caller is to delete
4694  *      this array using decrRef() as it is no more needed.
4695  */
4696 DataArrayInt *MEDCouplingUMesh::convertDegeneratedCellsAndRemoveFlatOnes()
4697 {
4698   checkFullyDefined();
4699   if(getMeshDimension()<=1)
4700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4701   int nbOfCells=getNumberOfCells();
4702   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
4703   if(nbOfCells<1)
4704     return ret;
4705   int initMeshLgth=getNodalConnectivityArrayLen();
4706   int *conn=_nodal_connec->getPointer();
4707   int *index=_nodal_connec_index->getPointer();
4708   int posOfCurCell=0;
4709   int newPos=0;
4710   int lgthOfCurCell, nbDelCells(0);
4711   for(int i=0;i<nbOfCells;i++)
4712     {
4713       lgthOfCurCell=index[i+1]-posOfCurCell;
4714       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4715       int newLgth;
4716       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4717                                                                                                      conn+newPos+1,newLgth);
4718       // Shall we delete the cell if it is completely degenerated:
4719       bool delCell=INTERP_KERNEL::CellSimplify::isFlatCell(conn, newPos, newLgth, newType);
4720       if (delCell)
4721         {
4722           nbDelCells++;
4723           ret->pushBackSilent(i);
4724         }
4725       else   //if the cell is to be deleted, simply stay at the same place
4726         {
4727           conn[newPos]=newType;
4728           newPos+=newLgth+1;
4729         }
4730       posOfCurCell=index[i+1];
4731       index[i+1-nbDelCells]=newPos;
4732     }
4733   if(newPos!=initMeshLgth)
4734     _nodal_connec->reAlloc(newPos);
4735   const int nCellDel=ret->getNumberOfTuples();
4736   if (nCellDel)
4737     _nodal_connec_index->reAlloc(nbOfCells-nCellDel+1);
4738   computeTypes();
4739   return ret.retn();
4740 }
4741
4742
4743 /*!
4744  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4745  * A cell is considered to be oriented correctly if an angle between its
4746  * normal vector and a given vector is less than \c PI / \c 2.
4747  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4748  *         cells. 
4749  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4750  *         checked.
4751  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4752  *         is not cleared before filling in.
4753  *  \throw If \a this->getMeshDimension() != 2.
4754  *  \throw If \a this->getSpaceDimension() != 3.
4755  *
4756  *  \if ENABLE_EXAMPLES
4757  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4758  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4759  *  \endif
4760  */
4761 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4762 {
4763   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4764     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4765   int nbOfCells=getNumberOfCells();
4766   const int *conn=_nodal_connec->begin();
4767   const int *connI=_nodal_connec_index->begin();
4768   const double *coordsPtr=_coords->begin();
4769   for(int i=0;i<nbOfCells;i++)
4770     {
4771       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4772       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4773         {
4774           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4775           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4776             cells.push_back(i);
4777         }
4778     }
4779 }
4780
4781 /*!
4782  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4783  * considered to be oriented correctly if an angle between its normal vector and a
4784  * given vector is less than \c PI / \c 2. 
4785  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4786  *         cells. 
4787  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4788  *         checked.
4789  *  \throw If \a this->getMeshDimension() != 2.
4790  *  \throw If \a this->getSpaceDimension() != 3.
4791  *
4792  *  \if ENABLE_EXAMPLES
4793  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4794  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4795  *  \endif
4796  *
4797  *  \sa changeOrientationOfCells
4798  */
4799 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4800 {
4801   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4802     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4803   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4804   const int *connI(_nodal_connec_index->begin());
4805   const double *coordsPtr(_coords->begin());
4806   bool isModified(false);
4807   for(int i=0;i<nbOfCells;i++)
4808     {
4809       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4810       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4811         {
4812           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4813           bool isQuadratic(cm.isQuadratic());
4814           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4815             {
4816               isModified=true;
4817               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4818             }
4819         }
4820     }
4821   if(isModified)
4822     _nodal_connec->declareAsNew();
4823   updateTime();
4824 }
4825
4826 /*!
4827  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4828  *
4829  * \sa orientCorrectly2DCells
4830  */
4831 void MEDCouplingUMesh::changeOrientationOfCells()
4832 {
4833   int mdim(getMeshDimension());
4834   if(mdim!=2 && mdim!=1)
4835     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4836   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4837   const int *connI(_nodal_connec_index->begin());
4838   if(mdim==2)
4839     {//2D
4840       for(int i=0;i<nbOfCells;i++)
4841         {
4842           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4843           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4844           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4845         }
4846     }
4847   else
4848     {//1D
4849       for(int i=0;i<nbOfCells;i++)
4850         {
4851           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4852           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4853           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4854         }
4855     }
4856 }
4857
4858 /*!
4859  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4860  * oriented facets. The normal vector of the facet should point out of the cell.
4861  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4862  *         is not cleared before filling in.
4863  *  \throw If \a this->getMeshDimension() != 3.
4864  *  \throw If \a this->getSpaceDimension() != 3.
4865  *  \throw If the coordinates array is not set.
4866  *  \throw If the nodal connectivity of cells is not defined.
4867  *
4868  *  \if ENABLE_EXAMPLES
4869  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4870  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4871  *  \endif
4872  */
4873 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4874 {
4875   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4876     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4877   int nbOfCells=getNumberOfCells();
4878   const int *conn=_nodal_connec->begin();
4879   const int *connI=_nodal_connec_index->begin();
4880   const double *coordsPtr=_coords->begin();
4881   for(int i=0;i<nbOfCells;i++)
4882     {
4883       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4884       if(type==INTERP_KERNEL::NORM_POLYHED)
4885         {
4886           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4887             cells.push_back(i);
4888         }
4889     }
4890 }
4891
4892 /*!
4893  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4894  * out of the cell. 
4895  *  \throw If \a this->getMeshDimension() != 3.
4896  *  \throw If \a this->getSpaceDimension() != 3.
4897  *  \throw If the coordinates array is not set.
4898  *  \throw If the nodal connectivity of cells is not defined.
4899  *  \throw If the reparation fails.
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  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4906  */
4907 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4908 {
4909   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4910     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4911   int nbOfCells=getNumberOfCells();
4912   int *conn=_nodal_connec->getPointer();
4913   const int *connI=_nodal_connec_index->begin();
4914   const double *coordsPtr=_coords->begin();
4915   for(int i=0;i<nbOfCells;i++)
4916     {
4917       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4918       if(type==INTERP_KERNEL::NORM_POLYHED)
4919         {
4920           try
4921           {
4922               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4923                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4924           }
4925           catch(INTERP_KERNEL::Exception& e)
4926           {
4927               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4928               throw INTERP_KERNEL::Exception(oss.str());
4929           }
4930         }
4931     }
4932   updateTime();
4933 }
4934
4935 /*!
4936  * This method invert orientation of all cells in \a this. 
4937  * After calling this method the absolute value of measure of cells in \a this are the same than before calling.
4938  * This method only operates on the connectivity so coordinates are not touched at all.
4939  */
4940 void MEDCouplingUMesh::invertOrientationOfAllCells()
4941 {
4942   checkConnectivityFullyDefined();
4943   std::set<INTERP_KERNEL::NormalizedCellType> gts(getAllGeoTypes());
4944   int *conn(_nodal_connec->getPointer());
4945   const int *conni(_nodal_connec_index->begin());
4946   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator gt=gts.begin();gt!=gts.end();gt++)
4947     {
4948       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::OrientationInverter> oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt));
4949       MCAuto<DataArrayInt> cwt(giveCellsWithType(*gt));
4950       for(const int *it=cwt->begin();it!=cwt->end();it++)
4951         oi->operate(conn+conni[*it]+1,conn+conni[*it+1]);
4952     }
4953   updateTime();
4954 }
4955
4956 /*!
4957  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4958  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4959  * according to which the first facet of the cell should be oriented to have the normal vector
4960  * pointing out of cell.
4961  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4962  *         cells. The caller is to delete this array using decrRef() as it is no more
4963  *         needed. 
4964  *  \throw If \a this->getMeshDimension() != 3.
4965  *  \throw If \a this->getSpaceDimension() != 3.
4966  *  \throw If the coordinates array is not set.
4967  *  \throw If the nodal connectivity of cells is not defined.
4968  *
4969  *  \if ENABLE_EXAMPLES
4970  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
4971  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
4972  *  \endif
4973  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4974  */
4975 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
4976 {
4977   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
4978   if(getMeshDimension()!=3)
4979     throw INTERP_KERNEL::Exception(msg);
4980   int spaceDim=getSpaceDimension();
4981   if(spaceDim!=3)
4982     throw INTERP_KERNEL::Exception(msg);
4983   //
4984   int nbOfCells=getNumberOfCells();
4985   int *conn=_nodal_connec->getPointer();
4986   const int *connI=_nodal_connec_index->begin();
4987   const double *coo=getCoords()->begin();
4988   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
4989   for(int i=0;i<nbOfCells;i++)
4990     {
4991       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4992       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
4993         {
4994           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
4995             {
4996               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4997               cells->pushBackSilent(i);
4998             }
4999         }
5000     }
5001   return cells.retn();
5002 }
5003
5004 /*!
5005  * This method is a faster method to correct orientation of all 3D cells in \a this.
5006  * 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.
5007  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
5008  * 
5009  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5010  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5011  */
5012 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5013 {
5014   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5015     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5016   int nbOfCells=getNumberOfCells();
5017   int *conn=_nodal_connec->getPointer();
5018   const int *connI=_nodal_connec_index->begin();
5019   const double *coordsPtr=_coords->begin();
5020   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5021   for(int i=0;i<nbOfCells;i++)
5022     {
5023       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5024       switch(type)
5025       {
5026         case INTERP_KERNEL::NORM_TETRA4:
5027           {
5028             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5029               {
5030                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5031                 ret->pushBackSilent(i);
5032               }
5033             break;
5034           }
5035         case INTERP_KERNEL::NORM_PYRA5:
5036           {
5037             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5038               {
5039                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5040                 ret->pushBackSilent(i);
5041               }
5042             break;
5043           }
5044         case INTERP_KERNEL::NORM_PENTA6:
5045         case INTERP_KERNEL::NORM_HEXA8:
5046         case INTERP_KERNEL::NORM_HEXGP12:
5047           {
5048             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5049               {
5050                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5051                 ret->pushBackSilent(i);
5052               }
5053             break;
5054           }
5055         case INTERP_KERNEL::NORM_POLYHED:
5056           {
5057             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5058               {
5059                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5060                 ret->pushBackSilent(i);
5061               }
5062             break;
5063           }
5064         default:
5065           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 !");
5066       }
5067     }
5068   updateTime();
5069   return ret.retn();
5070 }
5071
5072 /*!
5073  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5074  * If it is not the case an exception will be thrown.
5075  * This method is fast because the first cell of \a this is used to compute the plane.
5076  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5077  * \param pos output of size at least 3 used to store a point owned of searched plane.
5078  */
5079 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5080 {
5081   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5082     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5083   const int *conn=_nodal_connec->begin();
5084   const int *connI=_nodal_connec_index->begin();
5085   const double *coordsPtr=_coords->begin();
5086   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5087   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5088 }
5089
5090 /*!
5091  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5092  * cells. Currently cells of the following types are treated:
5093  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5094  * For a cell of other type an exception is thrown.
5095  * Space dimension of a 2D mesh can be either 2 or 3.
5096  * The Edge Ratio of a cell \f$t\f$ is: 
5097  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5098  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5099  *  the smallest edge lengths of \f$t\f$.
5100  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5101  *          cells and one time, lying on \a this mesh. The caller is to delete this
5102  *          field using decrRef() as it is no more needed. 
5103  *  \throw If the coordinates array is not set.
5104  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5105  *  \throw If the connectivity data array has more than one component.
5106  *  \throw If the connectivity data array has a named component.
5107  *  \throw If the connectivity index data array has more than one component.
5108  *  \throw If the connectivity index data array has a named component.
5109  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5110  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5111  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5112  */
5113 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5114 {
5115   checkConsistencyLight();
5116   int spaceDim=getSpaceDimension();
5117   int meshDim=getMeshDimension();
5118   if(spaceDim!=2 && spaceDim!=3)
5119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5120   if(meshDim!=2 && meshDim!=3)
5121     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5122   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5123   ret->setMesh(this);
5124   int nbOfCells=getNumberOfCells();
5125   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5126   arr->alloc(nbOfCells,1);
5127   double *pt=arr->getPointer();
5128   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5129   const int *conn=_nodal_connec->begin();
5130   const int *connI=_nodal_connec_index->begin();
5131   const double *coo=_coords->begin();
5132   double tmp[12];
5133   for(int i=0;i<nbOfCells;i++,pt++)
5134     {
5135       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5136       switch(t)
5137       {
5138         case INTERP_KERNEL::NORM_TRI3:
5139           {
5140             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5141             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5142             break;
5143           }
5144         case INTERP_KERNEL::NORM_QUAD4:
5145           {
5146             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5147             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5148             break;
5149           }
5150         case INTERP_KERNEL::NORM_TETRA4:
5151           {
5152             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5153             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5154             break;
5155           }
5156         default:
5157           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5158       }
5159       conn+=connI[i+1]-connI[i];
5160     }
5161   ret->setName("EdgeRatio");
5162   ret->synchronizeTimeWithSupport();
5163   return ret.retn();
5164 }
5165
5166 /*!
5167  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5168  * cells. Currently cells of the following types are treated:
5169  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5170  * For a cell of other type an exception is thrown.
5171  * Space dimension of a 2D mesh can be either 2 or 3.
5172  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5173  *          cells and one time, lying on \a this mesh. The caller is to delete this
5174  *          field using decrRef() as it is no more needed. 
5175  *  \throw If the coordinates array is not set.
5176  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5177  *  \throw If the connectivity data array has more than one component.
5178  *  \throw If the connectivity data array has a named component.
5179  *  \throw If the connectivity index data array has more than one component.
5180  *  \throw If the connectivity index data array has a named component.
5181  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5182  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5183  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5184  */
5185 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5186 {
5187   checkConsistencyLight();
5188   int spaceDim=getSpaceDimension();
5189   int meshDim=getMeshDimension();
5190   if(spaceDim!=2 && spaceDim!=3)
5191     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5192   if(meshDim!=2 && meshDim!=3)
5193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5194   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5195   ret->setMesh(this);
5196   int nbOfCells=getNumberOfCells();
5197   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5198   arr->alloc(nbOfCells,1);
5199   double *pt=arr->getPointer();
5200   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5201   const int *conn=_nodal_connec->begin();
5202   const int *connI=_nodal_connec_index->begin();
5203   const double *coo=_coords->begin();
5204   double tmp[12];
5205   for(int i=0;i<nbOfCells;i++,pt++)
5206     {
5207       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5208       switch(t)
5209       {
5210         case INTERP_KERNEL::NORM_TRI3:
5211           {
5212             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5213             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5214             break;
5215           }
5216         case INTERP_KERNEL::NORM_QUAD4:
5217           {
5218             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5219             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5220             break;
5221           }
5222         case INTERP_KERNEL::NORM_TETRA4:
5223           {
5224             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5225             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5226             break;
5227           }
5228         default:
5229           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5230       }
5231       conn+=connI[i+1]-connI[i];
5232     }
5233   ret->setName("AspectRatio");
5234   ret->synchronizeTimeWithSupport();
5235   return ret.retn();
5236 }
5237
5238 /*!
5239  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5240  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5241  * in 3D space. Currently only cells of the following types are
5242  * treated: INTERP_KERNEL::NORM_QUAD4.
5243  * For a cell of other type an exception is thrown.
5244  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5245  * Defining
5246  * \f$t=\vec{da}\times\vec{ab}\f$,
5247  * \f$u=\vec{ab}\times\vec{bc}\f$
5248  * \f$v=\vec{bc}\times\vec{cd}\f$
5249  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5250  *  \f[
5251  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5252  *  \f]
5253  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5254  *          cells and one time, lying on \a this mesh. The caller is to delete this
5255  *          field using decrRef() as it is no more needed. 
5256  *  \throw If the coordinates array is not set.
5257  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5258  *  \throw If the connectivity data array has more than one component.
5259  *  \throw If the connectivity data array has a named component.
5260  *  \throw If the connectivity index data array has more than one component.
5261  *  \throw If the connectivity index data array has a named component.
5262  *  \throw If \a this->getMeshDimension() != 2.
5263  *  \throw If \a this->getSpaceDimension() != 3.
5264  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5265  */
5266 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5267 {
5268   checkConsistencyLight();
5269   int spaceDim=getSpaceDimension();
5270   int meshDim=getMeshDimension();
5271   if(spaceDim!=3)
5272     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5273   if(meshDim!=2)
5274     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5275   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5276   ret->setMesh(this);
5277   int nbOfCells=getNumberOfCells();
5278   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5279   arr->alloc(nbOfCells,1);
5280   double *pt=arr->getPointer();
5281   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5282   const int *conn=_nodal_connec->begin();
5283   const int *connI=_nodal_connec_index->begin();
5284   const double *coo=_coords->begin();
5285   double tmp[12];
5286   for(int i=0;i<nbOfCells;i++,pt++)
5287     {
5288       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5289       switch(t)
5290       {
5291         case INTERP_KERNEL::NORM_QUAD4:
5292           {
5293             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5294             *pt=INTERP_KERNEL::quadWarp(tmp);
5295             break;
5296           }
5297         default:
5298           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5299       }
5300       conn+=connI[i+1]-connI[i];
5301     }
5302   ret->setName("Warp");
5303   ret->synchronizeTimeWithSupport();
5304   return ret.retn();
5305 }
5306
5307
5308 /*!
5309  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5310  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5311  * treated: INTERP_KERNEL::NORM_QUAD4.
5312  * The skew is computed as follow for a quad with points (a,b,c,d): let
5313  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5314  * then the skew is computed as:
5315  *  \f[
5316  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5317  *  \f]
5318  *
5319  * For a cell of other type an exception is thrown.
5320  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5321  *          cells and one time, lying on \a this mesh. The caller is to delete this
5322  *          field using decrRef() as it is no more needed. 
5323  *  \throw If the coordinates array is not set.
5324  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5325  *  \throw If the connectivity data array has more than one component.
5326  *  \throw If the connectivity data array has a named component.
5327  *  \throw If the connectivity index data array has more than one component.
5328  *  \throw If the connectivity index data array has a named component.
5329  *  \throw If \a this->getMeshDimension() != 2.
5330  *  \throw If \a this->getSpaceDimension() != 3.
5331  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5332  */
5333 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5334 {
5335   checkConsistencyLight();
5336   int spaceDim=getSpaceDimension();
5337   int meshDim=getMeshDimension();
5338   if(spaceDim!=3)
5339     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5340   if(meshDim!=2)
5341     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5342   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5343   ret->setMesh(this);
5344   int nbOfCells=getNumberOfCells();
5345   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5346   arr->alloc(nbOfCells,1);
5347   double *pt=arr->getPointer();
5348   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5349   const int *conn=_nodal_connec->begin();
5350   const int *connI=_nodal_connec_index->begin();
5351   const double *coo=_coords->begin();
5352   double tmp[12];
5353   for(int i=0;i<nbOfCells;i++,pt++)
5354     {
5355       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5356       switch(t)
5357       {
5358         case INTERP_KERNEL::NORM_QUAD4:
5359           {
5360             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5361             *pt=INTERP_KERNEL::quadSkew(tmp);
5362             break;
5363           }
5364         default:
5365           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5366       }
5367       conn+=connI[i+1]-connI[i];
5368     }
5369   ret->setName("Skew");
5370   ret->synchronizeTimeWithSupport();
5371   return ret.retn();
5372 }
5373
5374 /*!
5375  * 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.
5376  *
5377  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5378  *
5379  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5380  */
5381 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5382 {
5383   checkConsistencyLight();
5384   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5385   ret->setMesh(this);
5386   std::set<INTERP_KERNEL::NormalizedCellType> types;
5387   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5388   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5389   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5390   arr->alloc(nbCells,1);
5391   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5392     {
5393       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5394       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5395       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5396     }
5397   ret->setArray(arr);
5398   ret->setName("Diameter");
5399   return ret.retn();
5400 }
5401
5402 /*!
5403  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5404  * 
5405  * \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)
5406  *                         For all other cases this input parameter is ignored.
5407  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5408  * 
5409  * \throw If \a this is not fully set (coordinates and connectivity).
5410  * \throw If a cell in \a this has no valid nodeId.
5411  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5412  */
5413 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5414 {
5415   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5416   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.
5417     return getBoundingBoxForBBTreeFast();
5418   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5419     {
5420       bool presenceOfQuadratic(false);
5421       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5422         {
5423           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5424           if(cm.isQuadratic())
5425             presenceOfQuadratic=true;
5426         }
5427       if(!presenceOfQuadratic)
5428         return getBoundingBoxForBBTreeFast();
5429       if(mDim==2 && sDim==2)
5430         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5431       else
5432         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5433     }
5434   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) !");
5435 }
5436
5437 /*!
5438  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5439  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5440  * 
5441  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5442  * 
5443  * \throw If \a this is not fully set (coordinates and connectivity).
5444  * \throw If a cell in \a this has no valid nodeId.
5445  */
5446 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5447 {
5448   checkFullyDefined();
5449   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5450   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5451   double *bbox(ret->getPointer());
5452   for(int i=0;i<nbOfCells*spaceDim;i++)
5453     {
5454       bbox[2*i]=std::numeric_limits<double>::max();
5455       bbox[2*i+1]=-std::numeric_limits<double>::max();
5456     }
5457   const double *coordsPtr(_coords->begin());
5458   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5459   for(int i=0;i<nbOfCells;i++)
5460     {
5461       int offset=connI[i]+1;
5462       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5463       for(int j=0;j<nbOfNodesForCell;j++)
5464         {
5465           int nodeId=conn[offset+j];
5466           if(nodeId>=0 && nodeId<nbOfNodes)
5467             {
5468               for(int k=0;k<spaceDim;k++)
5469                 {
5470                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5471                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5472                 }
5473               kk++;
5474             }
5475         }
5476       if(kk==0)
5477         {
5478           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5479           throw INTERP_KERNEL::Exception(oss.str());
5480         }
5481     }
5482   return ret.retn();
5483 }
5484
5485 /*!
5486  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5487  * useful for 2D meshes having quadratic cells
5488  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5489  * the two extremities of the arc of circle).
5490  * 
5491  * \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)
5492  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5493  * \throw If \a this is not fully defined.
5494  * \throw If \a this is not a mesh with meshDimension equal to 2.
5495  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5496  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5497  */
5498 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5499 {
5500   checkFullyDefined();
5501   INTERP_KERNEL::QuadraticPlanarPrecision arcPrec(arcDetEps);
5502
5503   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5504   if(spaceDim!=2 || mDim!=2)
5505     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!");
5506   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5507   double *bbox(ret->getPointer());
5508   const double *coords(_coords->begin());
5509   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5510   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5511     {
5512       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5513       int sz(connI[1]-connI[0]-1);
5514       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5515       INTERP_KERNEL::QuadraticPolygon *pol(0);
5516       for(int j=0;j<sz;j++)
5517         {
5518           int nodeId(conn[*connI+1+j]);
5519           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5520         }
5521       if(!cm.isQuadratic())
5522         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5523       else
5524         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5525       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5526       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5527     }
5528   return ret.retn();
5529 }
5530
5531 /*!
5532  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5533  * useful for 2D meshes having quadratic cells
5534  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5535  * the two extremities of the arc of circle).
5536  * 
5537  * \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)
5538  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5539  * \throw If \a this is not fully defined.
5540  * \throw If \a this is not a mesh with meshDimension equal to 1.
5541  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5542  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5543  */
5544 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5545 {
5546   checkFullyDefined();
5547   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5548   if(spaceDim!=2 || mDim!=1)
5549     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!");
5550   INTERP_KERNEL::QuadraticPlanarPrecision arcPrec(arcDetEps);
5551   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5552   double *bbox(ret->getPointer());
5553   const double *coords(_coords->begin());
5554   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5555   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5556     {
5557       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5558       int sz(connI[1]-connI[0]-1);
5559       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5560       INTERP_KERNEL::Edge *edge(0);
5561       for(int j=0;j<sz;j++)
5562         {
5563           int nodeId(conn[*connI+1+j]);
5564           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5565         }
5566       if(!cm.isQuadratic())
5567         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5568       else
5569         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5570       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5571       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5572     }
5573   return ret.retn();
5574 }
5575
5576 /// @cond INTERNAL
5577
5578 namespace MEDCouplingImpl
5579 {
5580   class ConnReader
5581   {
5582   public:
5583     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5584     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5585   private:
5586     const int *_conn;
5587     int _val;
5588   };
5589
5590   class ConnReader2
5591   {
5592   public:
5593     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5594     bool operator() (const int& pos) { return _conn[pos]==_val; }
5595   private:
5596     const int *_conn;
5597     int _val;
5598   };
5599 }
5600
5601 /// @endcond
5602
5603 /*!
5604  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5605  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5606  * \a this is composed in cell types.
5607  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5608  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5609  * This parameter is kept only for compatibility with other method listed above.
5610  */
5611 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5612 {
5613   checkConnectivityFullyDefined();
5614   const int *conn=_nodal_connec->begin();
5615   const int *connI=_nodal_connec_index->begin();
5616   const int *work=connI;
5617   int nbOfCells=getNumberOfCells();
5618   std::size_t n=getAllGeoTypes().size();
5619   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5620   std::set<INTERP_KERNEL::NormalizedCellType> types;
5621   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5622     {
5623       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5624       if(types.find(typ)!=types.end())
5625         {
5626           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5627           oss << " is not contiguous !";
5628           throw INTERP_KERNEL::Exception(oss.str());
5629         }
5630       types.insert(typ);
5631       ret[3*i]=typ;
5632       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5633       ret[3*i+1]=(int)std::distance(work,work2);
5634       work=work2;
5635     }
5636   return ret;
5637 }
5638
5639 /*!
5640  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5641  * only for types cell, type node is not managed.
5642  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5643  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5644  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5645  * If 2 or more same geometric type is in \a code and exception is thrown too.
5646  *
5647  * This method firstly checks
5648  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5649  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5650  * an exception is thrown too.
5651  * 
5652  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5653  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5654  * and a DataArrayInt instance is returned that the user has the responsibility to deallocate.
5655  */
5656 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5657 {
5658   if(code.empty())
5659     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5660   std::size_t sz=code.size();
5661   std::size_t n=sz/3;
5662   if(sz%3!=0)
5663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5664   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5665   int nb=0;
5666   bool isNoPflUsed=true;
5667   for(std::size_t i=0;i<n;i++)
5668     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5669       {
5670         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5671         nb+=code[3*i+1];
5672         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5673           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5674         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5675       }
5676   if(types.size()!=n)
5677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5678   if(isNoPflUsed)
5679     {
5680       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5681         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5682       if(types.size()==_types.size())
5683         return 0;
5684     }
5685   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5686   ret->alloc(nb,1);
5687   int *retPtr=ret->getPointer();
5688   const int *connI=_nodal_connec_index->begin();
5689   const int *conn=_nodal_connec->begin();
5690   int nbOfCells=getNumberOfCells();
5691   const int *i=connI;
5692   int kk=0;
5693   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5694     {
5695       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5696       int offset=(int)std::distance(connI,i);
5697       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5698       int nbOfCellsOfCurType=(int)std::distance(i,j);
5699       if(code[3*kk+2]==-1)
5700         for(int k=0;k<nbOfCellsOfCurType;k++)
5701           *retPtr++=k+offset;
5702       else
5703         {
5704           int idInIdsPerType=code[3*kk+2];
5705           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5706             {
5707               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5708               if(zePfl)
5709                 {
5710                   zePfl->checkAllocated();
5711                   if(zePfl->getNumberOfComponents()==1)
5712                     {
5713                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5714                         {
5715                           if(*k>=0 && *k<nbOfCellsOfCurType)
5716                             *retPtr=(*k)+offset;
5717                           else
5718                             {
5719                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5720                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5721                               throw INTERP_KERNEL::Exception(oss.str());
5722                             }
5723                         }
5724                     }
5725                   else
5726                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5727                 }
5728               else
5729                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5730             }
5731           else
5732             {
5733               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5734               oss << " should be in [0," << idsPerType.size() << ") !";
5735               throw INTERP_KERNEL::Exception(oss.str());
5736             }
5737         }
5738       i=j;
5739     }
5740   return ret.retn();
5741 }
5742
5743 /*!
5744  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5745  * 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.
5746  * 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.
5747  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5748  * 
5749  * \param [in] profile
5750  * \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.
5751  * \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,
5752  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5753  * \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.
5754  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5755  * \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
5756  */
5757 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType, bool smartPflKiller) const
5758 {
5759   if(!profile)
5760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5761   if(profile->getNumberOfComponents()!=1)
5762     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5763   checkConnectivityFullyDefined();
5764   const int *conn=_nodal_connec->begin();
5765   const int *connI=_nodal_connec_index->begin();
5766   int nbOfCells=getNumberOfCells();
5767   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5768   std::vector<int> typeRangeVals(1);
5769   for(const int *i=connI;i!=connI+nbOfCells;)
5770     {
5771       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5772       if(std::find(types.begin(),types.end(),curType)!=types.end())
5773         {
5774           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5775         }
5776       types.push_back(curType);
5777       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5778       typeRangeVals.push_back((int)std::distance(connI,i));
5779     }
5780   //
5781   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5782   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5783   MCAuto<DataArrayInt> tmp0=castArr;
5784   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5785   MCAuto<DataArrayInt> tmp2=castsPresent;
5786   //
5787   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5788   code.resize(3*nbOfCastsFinal);
5789   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5790   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5791   for(int i=0;i<nbOfCastsFinal;i++)
5792     {
5793       int castId=castsPresent->getIJ(i,0);
5794       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5795       idsInPflPerType2.push_back(tmp3);
5796       code[3*i]=(int)types[castId];
5797       code[3*i+1]=tmp3->getNumberOfTuples();
5798       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5799       if(!smartPflKiller || !tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5800         {
5801           tmp4->copyStringInfoFrom(*profile);
5802           idsPerType2.push_back(tmp4);
5803           code[3*i+2]=(int)idsPerType2.size()-1;
5804         }
5805       else
5806         {
5807           code[3*i+2]=-1;
5808         }
5809     }
5810   std::size_t sz2=idsInPflPerType2.size();
5811   idsInPflPerType.resize(sz2);
5812   for(std::size_t i=0;i<sz2;i++)
5813     {
5814       DataArrayInt *locDa=idsInPflPerType2[i];
5815       locDa->incrRef();
5816       idsInPflPerType[i]=locDa;
5817     }
5818   std::size_t sz=idsPerType2.size();
5819   idsPerType.resize(sz);
5820   for(std::size_t i=0;i<sz;i++)
5821     {
5822       DataArrayInt *locDa=idsPerType2[i];
5823       locDa->incrRef();
5824       idsPerType[i]=locDa;
5825     }
5826 }
5827
5828 /*!
5829  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5830  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5831  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5832  * 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.
5833  */
5834 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5835 {
5836   checkFullyDefined();
5837   nM1LevMesh->checkFullyDefined();
5838   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5840   if(_coords!=nM1LevMesh->getCoords())
5841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5842   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5843   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5844   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5845   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5846   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5847   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5848   tmp->setConnectivity(tmp0,tmp1);
5849   tmp->renumberCells(ret0->begin(),false);
5850   revDesc=tmp->getNodalConnectivity();
5851   revDescIndx=tmp->getNodalConnectivityIndex();
5852   DataArrayInt *ret=0;
5853   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5854     {
5855       int tmp2;
5856       ret->getMaxValue(tmp2);
5857       ret->decrRef();
5858       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5859       throw INTERP_KERNEL::Exception(oss.str());
5860     }
5861   nM1LevMeshIds=ret;
5862   //
5863   revDesc->incrRef();
5864   revDescIndx->incrRef();
5865   ret1->incrRef();
5866   ret0->incrRef();
5867   meshnM1Old2New=ret0;
5868   return ret1;
5869 }
5870
5871 /*!
5872  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5873  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5874  * in "Old to New" mode.
5875  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5876  *          this array using decrRef() as it is no more needed.
5877  *  \throw If the nodal connectivity of cells is not defined.
5878  */
5879 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5880 {
5881   checkConnectivityFullyDefined();
5882   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5883   renumberCells(ret->begin(),false);
5884   return ret.retn();
5885 }
5886
5887 /*!
5888  * This methods checks that cells are sorted by their types.
5889  * This method makes asumption (no check) that connectivity is correctly set before calling.
5890  */
5891 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5892 {
5893   checkFullyDefined();
5894   const int *conn=_nodal_connec->begin();
5895   const int *connI=_nodal_connec_index->begin();
5896   int nbOfCells=getNumberOfCells();
5897   std::set<INTERP_KERNEL::NormalizedCellType> types;
5898   for(const int *i=connI;i!=connI+nbOfCells;)
5899     {
5900       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5901       if(types.find(curType)!=types.end())
5902         return false;
5903       types.insert(curType);
5904       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5905     }
5906   return true;
5907 }
5908
5909 /*!
5910  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5911  * The geometric type order is specified by MED file.
5912  * 
5913  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5914  */
5915 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5916 {
5917   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5918 }
5919
5920 /*!
5921  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5922  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5923  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5924  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5925  */
5926 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5927 {
5928   checkFullyDefined();
5929   const int *conn=_nodal_connec->begin();
5930   const int *connI=_nodal_connec_index->begin();
5931   int nbOfCells=getNumberOfCells();
5932   if(nbOfCells==0)
5933     return true;
5934   int lastPos=-1;
5935   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5936   for(const int *i=connI;i!=connI+nbOfCells;)
5937     {
5938       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5939       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5940       if(isTypeExists!=orderEnd)
5941         {
5942           int pos=(int)std::distance(orderBg,isTypeExists);
5943           if(pos<=lastPos)
5944             return false;
5945           lastPos=pos;
5946           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5947         }
5948       else
5949         {
5950           if(sg.find(curType)==sg.end())
5951             {
5952               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5953               sg.insert(curType);
5954             }
5955           else
5956             return false;
5957         }
5958     }
5959   return true;
5960 }
5961
5962 /*!
5963  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5964  * 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
5965  * 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'.
5966  */
5967 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
5968 {
5969   checkConnectivityFullyDefined();
5970   int nbOfCells=getNumberOfCells();
5971   const int *conn=_nodal_connec->begin();
5972   const int *connI=_nodal_connec_index->begin();
5973   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
5974   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
5975   tmpa->alloc(nbOfCells,1);
5976   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5977   tmpb->fillWithZero();
5978   int *tmp=tmpa->getPointer();
5979   int *tmp2=tmpb->getPointer();
5980   for(const int *i=connI;i!=connI+nbOfCells;i++)
5981     {
5982       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5983       if(where!=orderEnd)
5984         {
5985           int pos=(int)std::distance(orderBg,where);
5986           tmp2[pos]++;
5987           tmp[std::distance(connI,i)]=pos;
5988         }
5989       else
5990         {
5991           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5992           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5993           oss << " has a type " << cm.getRepr() << " not in input array of type !";
5994           throw INTERP_KERNEL::Exception(oss.str());
5995         }
5996     }
5997   nbPerType=tmpb.retn();
5998   return tmpa.retn();
5999 }
6000
6001 /*!
6002  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6003  *
6004  * \return a new object containing the old to new correspondence.
6005  *
6006  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6007  */
6008 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6009 {
6010   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6011 }
6012
6013 /*!
6014  * 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.
6015  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6016  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6017  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6018  */
6019 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6020 {
6021   DataArrayInt *nbPerType=0;
6022   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6023   nbPerType->decrRef();
6024   return tmpa->buildPermArrPerLevel();
6025 }
6026
6027 /*!
6028  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6029  * The number of cells remains unchanged after the call of this method.
6030  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6031  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6032  *
6033  * \return the array giving the correspondence old to new.
6034  */
6035 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6036 {
6037   checkFullyDefined();
6038   computeTypes();
6039   const int *conn=_nodal_connec->begin();
6040   const int *connI=_nodal_connec_index->begin();
6041   int nbOfCells=getNumberOfCells();
6042   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6043   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6044     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6045       {
6046         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6047         types.push_back(curType);
6048         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6049       }
6050   DataArrayInt *ret=DataArrayInt::New();
6051   ret->alloc(nbOfCells,1);
6052   int *retPtr=ret->getPointer();
6053   std::fill(retPtr,retPtr+nbOfCells,-1);
6054   int newCellId=0;
6055   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6056     {
6057       for(const int *i=connI;i!=connI+nbOfCells;i++)
6058         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6059           retPtr[std::distance(connI,i)]=newCellId++;
6060     }
6061   renumberCells(retPtr,false);
6062   return ret;
6063 }
6064
6065 /*!
6066  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6067  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6068  * This method makes asumption that connectivity is correctly set before calling.
6069  */
6070 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6071 {
6072   checkConnectivityFullyDefined();
6073   const int *conn=_nodal_connec->begin();
6074   const int *connI=_nodal_connec_index->begin();
6075   int nbOfCells=getNumberOfCells();
6076   std::vector<MEDCouplingUMesh *> ret;
6077   for(const int *i=connI;i!=connI+nbOfCells;)
6078     {
6079       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6080       int beginCellId=(int)std::distance(connI,i);
6081       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
6082       int endCellId=(int)std::distance(connI,i);
6083       int sz=endCellId-beginCellId;
6084       int *cells=new int[sz];
6085       for(int j=0;j<sz;j++)
6086         cells[j]=beginCellId+j;
6087       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6088       delete [] cells;
6089       ret.push_back(m);
6090     }
6091   return ret;
6092 }
6093
6094 /*!
6095  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6096  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6097  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6098  *
6099  * \return a newly allocated instance, that the caller must manage.
6100  * \throw If \a this contains more than one geometric type.
6101  * \throw If the nodal connectivity of \a this is not fully defined.
6102  * \throw If the internal data is not coherent.
6103  */
6104 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6105 {
6106   checkConnectivityFullyDefined();
6107   if(_types.size()!=1)
6108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6109   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6110   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6111   ret->setCoords(getCoords());
6112   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6113   if(retC)
6114     {
6115       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6116       retC->setNodalConnectivity(c);
6117     }
6118   else
6119     {
6120       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6121       if(!retD)
6122         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6123       DataArrayInt *c=0,*ci=0;
6124       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6125       MCAuto<DataArrayInt> cs(c),cis(ci);
6126       retD->setNodalConnectivity(cs,cis);
6127     }
6128   return ret.retn();
6129 }
6130
6131 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6132 {
6133   checkConnectivityFullyDefined();
6134   if(_types.size()!=1)
6135     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6136   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6137   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6138   if(cm.isDynamic())
6139     {
6140       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6141       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6142       throw INTERP_KERNEL::Exception(oss.str());
6143     }
6144   int nbCells=getNumberOfCells();
6145   int typi=(int)typ;
6146   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6147   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6148   int *outPtr=connOut->getPointer();
6149   const int *conn=_nodal_connec->begin();
6150   const int *connI=_nodal_connec_index->begin();
6151   nbNodesPerCell++;
6152   for(int i=0;i<nbCells;i++,connI++)
6153     {
6154       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6155         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6156       else
6157         {
6158           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 << ") !";
6159           throw INTERP_KERNEL::Exception(oss.str());
6160         }
6161     }
6162   return connOut.retn();
6163 }
6164
6165 /*!
6166  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6167  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6168  * \param nodalConn
6169  * \param nodalConnI
6170  */
6171 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6172 {
6173   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6174   checkConnectivityFullyDefined();
6175   if(_types.size()!=1)
6176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6177   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6178   if(lgth<nbCells)
6179     throw INTERP_KERNEL::Exception(msg0);
6180   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6181   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6182   int *cp(c->getPointer()),*cip(ci->getPointer());
6183   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6184   cip[0]=0;
6185   for(int i=0;i<nbCells;i++,cip++,incip++)
6186     {
6187       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6188       int delta(stop-strt);
6189       if(delta>=1)
6190         {
6191           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6192             cp=std::copy(incp+strt,incp+stop,cp);
6193           else
6194             throw INTERP_KERNEL::Exception(msg0);
6195         }
6196       else
6197         throw INTERP_KERNEL::Exception(msg0);
6198       cip[1]=cip[0]+delta;
6199     }
6200   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6201 }
6202
6203 /*!
6204  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6205  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6206  * This method is particularly useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6207  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6208  * are not used here to avoid the build of big permutation array.
6209  *
6210  * \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
6211  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6212  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6213  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6214  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6215  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6216  * \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
6217  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6218  */
6219 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6220                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6221                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6222 {
6223   std::vector<const MEDCouplingUMesh *> ms2;
6224   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6225     if(*it)
6226       {
6227         (*it)->checkConnectivityFullyDefined();
6228         ms2.push_back(*it);
6229       }
6230   if(ms2.empty())
6231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6232   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6233   int meshDim=ms2[0]->getMeshDimension();
6234   std::vector<const MEDCouplingUMesh *> m1ssm;
6235   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6236   //
6237   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6238   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6239   int fake=0,rk=0;
6240   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6241   ret1->alloc(0,1); ret2->alloc(0,1);
6242   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6243     {
6244       if(meshDim!=(*it)->getMeshDimension())
6245         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6246       if(refCoo!=(*it)->getCoords())
6247         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6248       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6249       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6250       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6251       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6252         {
6253           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6254           m1ssmSingleAuto.push_back(singleCell);
6255           m1ssmSingle.push_back(singleCell);
6256           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6257         }
6258     }
6259   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6260   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6261   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6262   for(std::size_t i=0;i<m1ssm.size();i++)
6263     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6264   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6265   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6266   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6267   return ret0.retn();
6268 }
6269
6270 /*!
6271  * This method returns a newly created DataArrayInt instance.
6272  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6273  */
6274 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6275 {
6276   checkFullyDefined();
6277   const int *conn=_nodal_connec->begin();
6278   const int *connIndex=_nodal_connec_index->begin();
6279   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6280   for(const int *w=begin;w!=end;w++)
6281     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6282       ret->pushBackSilent(*w);
6283   return ret.retn();
6284 }
6285
6286 /*!
6287  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6288  * are in [0:getNumberOfCells())
6289  */
6290 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6291 {
6292   checkFullyDefined();
6293   const int *conn=_nodal_connec->begin();
6294   const int *connI=_nodal_connec_index->begin();
6295   int nbOfCells=getNumberOfCells();
6296   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6297   int *tmp=new int[nbOfCells];
6298   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6299     {
6300       int j=0;
6301       for(const int *i=connI;i!=connI+nbOfCells;i++)
6302         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6303           tmp[std::distance(connI,i)]=j++;
6304     }
6305   DataArrayInt *ret=DataArrayInt::New();
6306   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6307   ret->copyStringInfoFrom(*da);
6308   int *retPtr=ret->getPointer();
6309   const int *daPtr=da->begin();
6310   int nbOfElems=da->getNbOfElems();
6311   for(int k=0;k<nbOfElems;k++)
6312     retPtr[k]=tmp[daPtr[k]];
6313   delete [] tmp;
6314   return ret;
6315 }
6316
6317 /*!
6318  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6319  * This method \b works \b for mesh sorted by type.
6320  * cells whose ids is in 'idsPerGeoType' array.
6321  * This method conserves coords and name of mesh.
6322  */
6323 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6324 {
6325   std::vector<int> code=getDistributionOfTypes();
6326   std::size_t nOfTypesInThis=code.size()/3;
6327   int sz=0,szOfType=0;
6328   for(std::size_t i=0;i<nOfTypesInThis;i++)
6329     {
6330       if(code[3*i]!=type)
6331         sz+=code[3*i+1];
6332       else
6333         szOfType=code[3*i+1];
6334     }
6335   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6336     if(*work<0 || *work>=szOfType)
6337       {
6338         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6339         oss << ". It should be in [0," << szOfType << ") !";
6340         throw INTERP_KERNEL::Exception(oss.str());
6341       }
6342   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6343   int *idsPtr=idsTokeep->getPointer();
6344   int offset=0;
6345   for(std::size_t i=0;i<nOfTypesInThis;i++)
6346     {
6347       if(code[3*i]!=type)
6348         for(int j=0;j<code[3*i+1];j++)
6349           *idsPtr++=offset+j;
6350       else
6351         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6352       offset+=code[3*i+1];
6353     }
6354   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6355   ret->copyTinyInfoFrom(this);
6356   return ret.retn();
6357 }
6358
6359 /*!
6360  * This method returns a vector of size 'this->getNumberOfCells()'.
6361  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6362  */
6363 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6364 {
6365   int ncell=getNumberOfCells();
6366   std::vector<bool> ret(ncell);
6367   const int *cI=getNodalConnectivityIndex()->begin();
6368   const int *c=getNodalConnectivity()->begin();
6369   for(int i=0;i<ncell;i++)
6370     {
6371       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6372       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6373       ret[i]=cm.isQuadratic();
6374     }
6375   return ret;
6376 }
6377
6378 /*!
6379  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6380  */
6381 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6382 {
6383   if(other->getType()!=UNSTRUCTURED)
6384     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6385   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6386   return MergeUMeshes(this,otherC);
6387 }
6388
6389 /*!
6390  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6391  * computed by averaging coordinates of cell nodes, so this method is not a right
6392  * choice for degenerated meshes (not well oriented, cells with measure close to zero).
6393  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6394  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6395  *          components. The caller is to delete this array using decrRef() as it is
6396  *          no more needed.
6397  *  \throw If the coordinates array is not set.
6398  *  \throw If the nodal connectivity of cells is not defined.
6399  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6400  */
6401 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6402 {
6403   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6404   int spaceDim=getSpaceDimension();
6405   int nbOfCells=getNumberOfCells();
6406   ret->alloc(nbOfCells,spaceDim);
6407   ret->copyStringInfoFrom(*getCoords());
6408   double *ptToFill=ret->getPointer();
6409   const int *nodal=_nodal_connec->begin();
6410   const int *nodalI=_nodal_connec_index->begin();
6411   const double *coor=_coords->begin();
6412   for(int i=0;i<nbOfCells;i++)
6413     {
6414       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6415       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6416       ptToFill+=spaceDim;
6417     }
6418   return ret.retn();
6419 }
6420
6421 /*!
6422  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6423  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6424  * 
6425  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6426  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6427  * 
6428  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6429  * \throw If \a this is not fully defined (coordinates and connectivity)
6430  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6431  */
6432 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6433 {
6434   checkFullyDefined();
6435   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6436   int spaceDim=getSpaceDimension();
6437   int nbOfCells=getNumberOfCells();
6438   int nbOfNodes=getNumberOfNodes();
6439   ret->alloc(nbOfCells,spaceDim);
6440   double *ptToFill=ret->getPointer();
6441   const int *nodal=_nodal_connec->begin();
6442   const int *nodalI=_nodal_connec_index->begin();
6443   const double *coor=_coords->begin();
6444   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6445     {
6446       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6447       std::fill(ptToFill,ptToFill+spaceDim,0.);
6448       if(type!=INTERP_KERNEL::NORM_POLYHED)
6449         {
6450           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6451             {
6452               if(*conn>=0 && *conn<nbOfNodes)
6453                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6454               else
6455                 {
6456                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6457                   throw INTERP_KERNEL::Exception(oss.str());
6458                 }
6459             }
6460           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6461           if(nbOfNodesInCell>0)
6462             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6463           else
6464             {
6465               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6466               throw INTERP_KERNEL::Exception(oss.str());
6467             }
6468         }
6469       else
6470         {
6471           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6472           s.erase(-1);
6473           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6474             {
6475               if(*it>=0 && *it<nbOfNodes)
6476                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6477               else
6478                 {
6479                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6480                   throw INTERP_KERNEL::Exception(oss.str());
6481                 }
6482             }
6483           if(!s.empty())
6484             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6485           else
6486             {
6487               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6488               throw INTERP_KERNEL::Exception(oss.str());
6489             }
6490         }
6491     }
6492   return ret.retn();
6493 }
6494
6495 /*!
6496  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6497  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6498  * are specified via an array of cell ids. 
6499  *  \warning Validity of the specified cell ids is not checked! 
6500  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6501  *  \param [in] begin - an array of cell ids of interest.
6502  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6503  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6504  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6505  *          caller is to delete this array using decrRef() as it is no more needed. 
6506  *  \throw If the coordinates array is not set.
6507  *  \throw If the nodal connectivity of cells is not defined.
6508  *
6509  *  \if ENABLE_EXAMPLES
6510  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6511  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6512  *  \endif
6513  */
6514 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6515 {
6516   DataArrayDouble *ret=DataArrayDouble::New();
6517   int spaceDim=getSpaceDimension();
6518   int nbOfTuple=(int)std::distance(begin,end);
6519   ret->alloc(nbOfTuple,spaceDim);
6520   double *ptToFill=ret->getPointer();
6521   double *tmp=new double[spaceDim];
6522   const int *nodal=_nodal_connec->begin();
6523   const int *nodalI=_nodal_connec_index->begin();
6524   const double *coor=_coords->begin();
6525   for(const int *w=begin;w!=end;w++)
6526     {
6527       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6528       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6529       ptToFill+=spaceDim;
6530     }
6531   delete [] tmp;
6532   return ret;
6533 }
6534
6535 /*!
6536  * 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".
6537  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6538  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6539  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6540  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6541  * 
6542  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6543  * \throw If spaceDim!=3 or meshDim!=2.
6544  * \throw If connectivity of \a this is invalid.
6545  * \throw If connectivity of a cell in \a this points to an invalid node.
6546  */
6547 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6548 {
6549   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6550   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6551   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6552     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6553   ret->alloc(nbOfCells,4);
6554   double *retPtr(ret->getPointer());
6555   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6556   const double *coor(_coords->begin());
6557   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6558     {
6559       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6560       if(nodalI[1]-nodalI[0]>=4)
6561         {
6562           double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6563                         coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6564                         coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}
6565           ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6566                         coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6567                         coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]};
6568           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]};
6569           for(int j=0;j<3;j++)
6570             {
6571               int nodeId(nodal[nodalI[0]+1+j]);
6572               if(nodeId>=0 && nodeId<nbOfNodes)
6573                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6574               else
6575                 {
6576                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6577                   throw INTERP_KERNEL::Exception(oss.str());
6578                 }
6579             }
6580           if(sqrt(cc[0]*cc[0]+cc[1]*cc[1]+cc[2]*cc[2])>1e-7)
6581             {
6582               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6583               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6584             }
6585           else
6586             {
6587               if(nodalI[1]-nodalI[0]==4)
6588                 {
6589                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !";
6590                   throw INTERP_KERNEL::Exception(oss.str());
6591                 }
6592               //
6593               double dd[3]={0.,0.,0.};
6594               for(int offset=nodalI[0]+1;offset<nodalI[1];offset++)
6595                 std::transform(coor+3*nodal[offset],coor+3*(nodal[offset]+1),dd,dd,std::plus<double>());
6596               int nbOfNodesInCell(nodalI[1]-nodalI[0]-1);
6597               std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6598               std::copy(dd,dd+3,matrix+4*2);
6599               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6600               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6601             }
6602         }
6603       else
6604         {
6605           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6606           throw INTERP_KERNEL::Exception(oss.str());
6607         }
6608     }
6609   return ret.retn();
6610 }
6611
6612 /*!
6613  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6614  * 
6615  */
6616 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6617 {
6618   if(!da)
6619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6620   da->checkAllocated();
6621   std::string name(da->getName());
6622   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6623   if(name.empty())
6624     ret->setName("Mesh");
6625   ret->setCoords(da);
6626   int nbOfTuples(da->getNumberOfTuples());
6627   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6628   c->alloc(2*nbOfTuples,1);
6629   cI->alloc(nbOfTuples+1,1);
6630   int *cp(c->getPointer()),*cip(cI->getPointer());
6631   *cip++=0;
6632   for(int i=0;i<nbOfTuples;i++)
6633     {
6634       *cp++=INTERP_KERNEL::NORM_POINT1;
6635       *cp++=i;
6636       *cip++=2*(i+1);
6637     }
6638   ret->setConnectivity(c,cI,true);
6639   return ret.retn();
6640 }
6641
6642 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6643 {
6644   if(!da)
6645     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6646   da->checkAllocated();
6647   std::string name(da->getName());
6648   MCAuto<MEDCouplingUMesh> ret;
6649   {
6650     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6651     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6652     arr->alloc(da->getNumberOfTuples());
6653     tmp->setCoordsAt(0,arr);
6654     ret=tmp->buildUnstructured();
6655   }
6656   ret->setCoords(da);
6657   if(name.empty())
6658     ret->setName("Mesh");
6659   else
6660     ret->setName(name);
6661   return ret;
6662 }
6663
6664 /*!
6665  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6666  * Cells and nodes of
6667  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6668  *  \param [in] mesh1 - the first mesh.
6669  *  \param [in] mesh2 - the second mesh.
6670  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6671  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6672  *          is no more needed.
6673  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6674  *  \throw If the coordinates array is not set in none of the meshes.
6675  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6676  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6677  */
6678 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6679 {
6680   std::vector<const MEDCouplingUMesh *> tmp(2);
6681   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6682   return MergeUMeshes(tmp);
6683 }
6684
6685 /*!
6686  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6687  * Cells and nodes of
6688  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6689  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6690  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6691  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6692  *          is no more needed.
6693  *  \throw If \a a.size() == 0.
6694  *  \throw If \a a[ *i* ] == NULL.
6695  *  \throw If the coordinates array is not set in none of the meshes.
6696  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6697  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6698  */
6699 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6700 {
6701   std::size_t sz=a.size();
6702   if(sz==0)
6703     return MergeUMeshesLL(a);
6704   for(std::size_t ii=0;ii<sz;ii++)
6705     if(!a[ii])
6706       {
6707         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6708         throw INTERP_KERNEL::Exception(oss.str());
6709       }
6710   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6711   std::vector< const MEDCouplingUMesh * > aa(sz);
6712   int spaceDim=-3;
6713   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6714     {
6715       const MEDCouplingUMesh *cur=a[i];
6716       const DataArrayDouble *coo=cur->getCoords();
6717       if(coo)
6718         spaceDim=coo->getNumberOfComponents();
6719     }
6720   if(spaceDim==-3)
6721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6722   for(std::size_t i=0;i<sz;i++)
6723     {
6724       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6725       aa[i]=bb[i];
6726     }
6727   return MergeUMeshesLL(aa);
6728 }
6729
6730 /*!
6731  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6732  * dimension and sharing the node coordinates array.
6733  * All cells of the first mesh precede all cells of the second mesh
6734  * within the result mesh.
6735  *  \param [in] mesh1 - the first mesh.
6736  *  \param [in] mesh2 - the second mesh.
6737  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6738  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6739  *          is no more needed.
6740  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6741  *  \throw If the meshes do not share the node coordinates array.
6742  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6743  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6744  */
6745 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6746 {
6747   std::vector<const MEDCouplingUMesh *> tmp(2);
6748   tmp[0]=mesh1; tmp[1]=mesh2;
6749   return MergeUMeshesOnSameCoords(tmp);
6750 }
6751
6752 /*!
6753  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6754  * dimension and sharing the node coordinates array.
6755  * All cells of the *i*-th mesh precede all cells of the
6756  * (*i*+1)-th mesh within the result mesh.
6757  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6758  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6759  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6760  *          is no more needed.
6761  *  \throw If \a a.size() == 0.
6762  *  \throw If \a a[ *i* ] == NULL.
6763  *  \throw If the meshes do not share the node coordinates array.
6764  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6765  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6766  */
6767 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6768 {
6769   if(meshes.empty())
6770     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6771   for(std::size_t ii=0;ii<meshes.size();ii++)
6772     if(!meshes[ii])
6773       {
6774         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6775         throw INTERP_KERNEL::Exception(oss.str());
6776       }
6777   const DataArrayDouble *coords=meshes.front()->getCoords();
6778   int meshDim=meshes.front()->getMeshDimension();
6779   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6780   int meshLgth=0;
6781   int meshIndexLgth=0;
6782   for(;iter!=meshes.end();iter++)
6783     {
6784       if(coords!=(*iter)->getCoords())
6785         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6786       if(meshDim!=(*iter)->getMeshDimension())
6787         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6788       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6789       meshIndexLgth+=(*iter)->getNumberOfCells();
6790     }
6791   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6792   nodal->alloc(meshLgth,1);
6793   int *nodalPtr=nodal->getPointer();
6794   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6795   nodalIndex->alloc(meshIndexLgth+1,1);
6796   int *nodalIndexPtr=nodalIndex->getPointer();
6797   int offset=0;
6798   for(iter=meshes.begin();iter!=meshes.end();iter++)
6799     {
6800       const int *nod=(*iter)->getNodalConnectivity()->begin();
6801       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6802       int nbOfCells=(*iter)->getNumberOfCells();
6803       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6804       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6805       if(iter!=meshes.begin())
6806         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6807       else
6808         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6809       offset+=meshLgth2;
6810     }
6811   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6812   ret->setName("merge");
6813   ret->setMeshDimension(meshDim);
6814   ret->setConnectivity(nodal,nodalIndex,true);
6815   ret->setCoords(coords);
6816   return ret;
6817 }
6818
6819 /*!
6820  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6821  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6822  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6823  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6824  * New" mode are returned for each input mesh.
6825  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6826  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6827  *          valid values [0,1,2], see zipConnectivityTraducer().
6828  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6829  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6830  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6831  *          no more needed.
6832  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6833  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6834  *          is no more needed.
6835  *  \throw If \a meshes.size() == 0.
6836  *  \throw If \a meshes[ *i* ] == NULL.
6837  *  \throw If the meshes do not share the node coordinates array.
6838  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6839  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6840  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6841  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6842  */
6843 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6844 {
6845   //All checks are delegated to MergeUMeshesOnSameCoords
6846   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6847   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6848   corr.resize(meshes.size());
6849   std::size_t nbOfMeshes=meshes.size();
6850   int offset=0;
6851   const int *o2nPtr=o2n->begin();
6852   for(std::size_t i=0;i<nbOfMeshes;i++)
6853     {
6854       DataArrayInt *tmp=DataArrayInt::New();
6855       int curNbOfCells=meshes[i]->getNumberOfCells();
6856       tmp->alloc(curNbOfCells,1);
6857       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6858       offset+=curNbOfCells;
6859       tmp->setName(meshes[i]->getName());
6860       corr[i]=tmp;
6861     }
6862   return ret.retn();
6863 }
6864
6865 /*!
6866  * Makes all given meshes share the nodal connectivity array. The common connectivity
6867  * array is created by concatenating the connectivity arrays of all given meshes. All
6868  * the given meshes must be of the same space dimension but dimension of cells **can
6869  * differ**. This method is particularly useful in MEDLoader context to build a \ref
6870  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6871  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6872  *  \param [in,out] meshes - a vector of meshes to update.
6873  *  \throw If any of \a meshes is NULL.
6874  *  \throw If the coordinates array is not set in any of \a meshes.
6875  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6876  *  \throw If \a meshes are of different space dimension.
6877  */
6878 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6879 {
6880   std::size_t sz=meshes.size();
6881   if(sz==0 || sz==1)
6882     return;
6883   std::vector< const DataArrayDouble * > coords(meshes.size());
6884   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6885   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6886     {
6887       if((*it))
6888         {
6889           (*it)->checkConnectivityFullyDefined();
6890           const DataArrayDouble *coo=(*it)->getCoords();
6891           if(coo)
6892             *it2=coo;
6893           else
6894             {
6895               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6896               oss << " has no coordinate array defined !";
6897               throw INTERP_KERNEL::Exception(oss.str());
6898             }
6899         }
6900       else
6901         {
6902           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6903           oss << " is null !";
6904           throw INTERP_KERNEL::Exception(oss.str());
6905         }
6906     }
6907   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6908   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6909   int offset=(*it)->getNumberOfNodes();
6910   (*it++)->setCoords(res);
6911   for(;it!=meshes.end();it++)
6912     {
6913       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6914       (*it)->setCoords(res);
6915       (*it)->shiftNodeNumbersInConn(offset);
6916       offset+=oldNumberOfNodes;
6917     }
6918 }
6919
6920 /*!
6921  * Merges nodes coincident with a given precision within all given meshes that share
6922  * the nodal connectivity array. The given meshes **can be of different** mesh
6923  * dimension. This method is particularly useful in MEDLoader context to build a \ref
6924  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6925  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6926  *  \param [in,out] meshes - a vector of meshes to update.
6927  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6928  *  \throw If any of \a meshes is NULL.
6929  *  \throw If the \a meshes do not share the same node coordinates array.
6930  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6931  */
6932 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6933 {
6934   if(meshes.empty())
6935     return ;
6936   std::set<const DataArrayDouble *> s;
6937   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6938     {
6939       if(*it)
6940         s.insert((*it)->getCoords());
6941       else
6942         {
6943           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 !";
6944           throw INTERP_KERNEL::Exception(oss.str());
6945         }
6946     }
6947   if(s.size()!=1)
6948     {
6949       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 !";
6950       throw INTERP_KERNEL::Exception(oss.str());
6951     }
6952   const DataArrayDouble *coo=*(s.begin());
6953   if(!coo)
6954     return;
6955   //
6956   DataArrayInt *comm,*commI;
6957   coo->findCommonTuples(eps,-1,comm,commI);
6958   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6959   int oldNbOfNodes=coo->getNumberOfTuples();
6960   int newNbOfNodes;
6961   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6962   if(oldNbOfNodes==newNbOfNodes)
6963     return ;
6964   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6965   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6966     {
6967       (*it)->renumberNodesInConn(o2n->begin());
6968       (*it)->setCoords(newCoords);
6969     } 
6970 }
6971
6972
6973 /*!
6974  * This static operates only for coords in 3D. The polygon is specified by its connectivity nodes in [ \a begin , \a end ).
6975  */
6976 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6977 {
6978   std::size_t i, ip1;
6979   double v[3]={0.,0.,0.};
6980   std::size_t sz=std::distance(begin,end);
6981   if(isQuadratic)
6982     sz/=2;
6983   for(i=0;i<sz;i++)
6984     {
6985       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];
6986       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6987       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6988     }
6989   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6990
6991   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
6992   // SEG3 forming a circle):
6993   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
6994     {
6995       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
6996       for(std::size_t j=0;j<sz;j++)
6997         {
6998           if (j%2)  // current point i is quadratic, next point i+1 is standard
6999             {
7000               i = sz+j;
7001               ip1 = (j+1)%sz; // ip1 = "i+1"
7002             }
7003           else      // current point i is standard, next point i+1 is quadratic
7004             {
7005               i = j;
7006               ip1 = j+sz;
7007             }
7008           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7009           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7010           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7011         }
7012       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7013     }
7014   return (ret>0.);
7015 }
7016
7017 /*!
7018  * The polyhedron is specified by its connectivity nodes in [ \a begin , \a end ).
7019  */
7020 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7021 {
7022   std::vector<std::pair<int,int> > edges;
7023   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7024   const int *bgFace=begin;
7025   for(std::size_t i=0;i<nbOfFaces;i++)
7026     {
7027       const int *endFace=std::find(bgFace+1,end,-1);
7028       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7029       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7030         {
7031           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7032           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7033             return false;
7034           edges.push_back(p1);
7035         }
7036       bgFace=endFace+1;
7037     }
7038   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7039 }
7040
7041 /*!
7042  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7043  */
7044 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7045 {
7046   double vec0[3],vec1[3];
7047   std::size_t sz=std::distance(begin,end);
7048   if(sz%2!=0)
7049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7050   int nbOfNodes=(int)sz/2;
7051   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7052   const double *pt0=coords+3*begin[0];
7053   const double *pt1=coords+3*begin[nbOfNodes];
7054   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7055   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7056 }
7057
7058 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7059 {
7060   std::size_t sz=std::distance(begin,end);
7061   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7062   std::size_t nbOfNodes(sz/2);
7063   std::copy(begin,end,(int *)tmp);
7064   for(std::size_t j=1;j<nbOfNodes;j++)
7065     {
7066       begin[j]=tmp[nbOfNodes-j];
7067       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7068     }
7069 }
7070
7071 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7072 {
7073   std::size_t sz=std::distance(begin,end);
7074   if(sz!=4)
7075     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
7076   double vec0[3],vec1[3];
7077   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7078   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]; 
7079   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;
7080 }
7081
7082 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7083 {
7084   std::size_t sz=std::distance(begin,end);
7085   if(sz!=5)
7086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
7087   double vec0[3];
7088   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7089   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7090   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7091 }
7092
7093 /*!
7094  * 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 ) 
7095  * 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
7096  * a 2D space.
7097  *
7098  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7099  * \param [in] coords the coordinates with nb of components exactly equal to 3
7100  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7101  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7102  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7103  */
7104 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, int index, DataArrayInt *res, MEDCouplingUMesh *faces,
7105                                               DataArrayInt *E_Fi, DataArrayInt *E_F, DataArrayInt *F_Ei, DataArrayInt *F_E)
7106 {
7107   int nbFaces = E_Fi->getIJ(index + 1, 0) - E_Fi->getIJ(index, 0);
7108   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7109   double *vPtr=v->getPointer();
7110   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,2);
7111   double *pPtr=p->getPointer();
7112   int *e_fi = E_Fi->getPointer(), *e_f = E_F->getPointer(), *f_ei = F_Ei->getPointer(), *f_e = F_E->getPointer();
7113   const int *f_idx = faces->getNodalConnectivityIndex()->getPointer(), *f_cnn = faces->getNodalConnectivity()->getPointer();
7114   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7115     {
7116       int face = e_f[e_fi[index] + i];
7117       ComputeVecAndPtOfFace(eps, coords->begin(), f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1], vPtr, pPtr);
7118       // to differentiate faces going to different cells:
7119       pPtr++, *pPtr = 0;
7120       for (int j = f_ei[face]; j < f_ei[face + 1]; j++)
7121         *pPtr += f_e[j];
7122     }
7123   pPtr=p->getPointer(); vPtr=v->getPointer();
7124   DataArrayInt *comm1=0,*commI1=0;
7125   v->findCommonTuples(eps,-1,comm1,commI1);
7126   for (int i = 0; i < nbFaces; i++)
7127     if (comm1->findIdFirstEqual(i) < 0)
7128       {
7129         comm1->pushBackSilent(i);
7130         commI1->pushBackSilent(comm1->getNumberOfTuples());
7131       }
7132   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7133   const int *comm1Ptr=comm1->begin();
7134   const int *commI1Ptr=commI1->begin();
7135   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7136   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7137   //
7138   for(int i=0;i<nbOfGrps1;i++)
7139     {
7140       int vecId=comm1Ptr[commI1Ptr[i]];
7141       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7142       DataArrayInt *comm2=0,*commI2=0;
7143       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7144       for (int j = 0; j < commI1Ptr[i+1] - commI1Ptr[i]; j++)
7145         if (comm2->findIdFirstEqual(j) < 0)
7146           {
7147             comm2->pushBackSilent(j);
7148             commI2->pushBackSilent(comm2->getNumberOfTuples());
7149           }
7150       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7151       const int *comm2Ptr=comm2->begin();
7152       const int *commI2Ptr=commI2->begin();
7153       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7154       for(int j=0;j<nbOfGrps2;j++)
7155         {
7156           if(commI2Ptr[j+1] == commI2Ptr[j] + 1)
7157             {
7158               int face = e_f[e_fi[index] + comm1Ptr[commI1Ptr[i] + comm2Ptr[commI2Ptr[j]]]]; //hmmm
7159               res->insertAtTheEnd(f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1]);
7160               res->pushBackSilent(-1);
7161             }
7162           else
7163             {
7164               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7165               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7166               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7167               ids2->transformWithIndArr(e_f + e_fi[index], e_f + e_fi[index + 1]);
7168               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(faces->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7169               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7170               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7171               const int *idsNodePtr=idsNode->begin();
7172               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];
7173               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7174               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7175               if(std::abs(norm)>eps)
7176                 {
7177                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7178                   mm3->rotate(center,vec,angle);
7179                 }
7180               mm3->changeSpaceDimension(2);
7181               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7182               const int *conn4=mm4->getNodalConnectivity()->begin();
7183               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7184               int nbOfCells=mm4->getNumberOfCells();
7185               for(int k=0;k<nbOfCells;k++)
7186                 {
7187                   int l=0;
7188                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7189                     res->pushBackSilent(idsNodePtr[*work]);
7190                   res->pushBackSilent(-1);
7191                 }
7192             }
7193         }
7194     }
7195   res->popBackSilent();
7196 }
7197
7198 /*!
7199  * 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
7200  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7201  * 
7202  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7203  * \param [in] coords coordinates expected to have 3 components.
7204  * \param [in] begin start of the nodal connectivity of the face.
7205  * \param [in] end end of the nodal connectivity (excluded) of the face.
7206  * \param [out] v the normalized vector of size 3
7207  * \param [out] p the pos of plane
7208  */
7209 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7210 {
7211   std::size_t nbPoints=std::distance(begin,end);
7212   if(nbPoints<3)
7213     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7214   double vec[3]={0.,0.,0.};
7215   std::size_t j=0;
7216   bool refFound=false;
7217   for(;j<nbPoints-1 && !refFound;j++)
7218     {
7219       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7220       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7221       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7222       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7223       if(norm>eps)
7224         {
7225           refFound=true;
7226           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7227         }
7228     }
7229   for(std::size_t i=j;i<nbPoints-1;i++)
7230     {
7231       double curVec[3];
7232       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7233       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7234       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7235       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7236       if(norm<eps)
7237         continue;
7238       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7239       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];
7240       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7241       if(norm>eps)
7242         {
7243           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7244           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7245           return ;
7246         }
7247     }
7248   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7249 }
7250
7251 /*!
7252  * This method tries to obtain a well oriented polyhedron.
7253  * If the algorithm fails, an exception will be thrown.
7254  */
7255 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7256 {
7257   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7258   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7259   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7260   isPerm[0]=true;
7261   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7262   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7263   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7264   //
7265   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7266     {
7267       bgFace=begin;
7268       std::size_t smthChanged=0;
7269       for(std::size_t i=0;i<nbOfFaces;i++)
7270         {
7271           endFace=std::find(bgFace+1,end,-1);
7272           nbOfEdgesInFace=std::distance(bgFace,endFace);
7273           if(!isPerm[i])
7274             {
7275               bool b;
7276               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7277                 {
7278                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7279                   std::pair<int,int> p2(p1.second,p1.first);
7280                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7281                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7282                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7283                 }
7284               if(isPerm[i])
7285                 { 
7286                   if(!b)
7287                     std::reverse(bgFace+1,endFace);
7288                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7289                     {
7290                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7291                       std::pair<int,int> p2(p1.second,p1.first);
7292                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7293                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7294                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7295                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7296                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7297                       if(it!=edgesOK.end())
7298                         {
7299                           edgesOK.erase(it);
7300                           edgesFinished.push_back(p1);
7301                         }
7302                       else
7303                         edgesOK.push_back(p1);
7304                     }
7305                 }
7306             }
7307           bgFace=endFace+1;
7308         }
7309       if(smthChanged==0)
7310         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7311     }
7312   if(!edgesOK.empty())
7313     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7314   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7315     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7316       bgFace=begin;
7317       for(std::size_t i=0;i<nbOfFaces;i++)
7318         {
7319           endFace=std::find(bgFace+1,end,-1);
7320           std::reverse(bgFace+1,endFace);
7321           bgFace=endFace+1;
7322         }
7323     }
7324 }
7325
7326
7327 /*!
7328  * This method makes the assumption spacedimension == meshdimension == 2.
7329  * This method works only for linear cells.
7330  * 
7331  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7332  */
7333 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7334 {
7335   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7336     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7337   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7338   int oldNbOfNodes(skin->getNumberOfNodes());
7339   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7340   int nbOfNodesExpected(skin->getNumberOfNodes());
7341   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7342   int nbCells(skin->getNumberOfCells());
7343   if(nbCells==nbOfNodesExpected)
7344     return buildUnionOf2DMeshLinear(skin,n2o);
7345   else if(2*nbCells==nbOfNodesExpected)
7346     return buildUnionOf2DMeshQuadratic(skin,n2o);
7347   else
7348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7349 }
7350
7351 /*!
7352  * This method makes the assumption spacedimension == meshdimension == 3.
7353  * This method works only for linear cells.
7354  * 
7355  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7356  */
7357 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7358 {
7359   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7360     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7361   MCAuto<MEDCouplingUMesh> m=computeSkin();
7362   const int *conn=m->getNodalConnectivity()->begin();
7363   const int *connI=m->getNodalConnectivityIndex()->begin();
7364   int nbOfCells=m->getNumberOfCells();
7365   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7366   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7367   if(nbOfCells<1)
7368     return ret.retn();
7369   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7370   for(int i=1;i<nbOfCells;i++)
7371     {
7372       *work++=-1;
7373       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7374     }
7375   return ret.retn();
7376 }
7377
7378 /*!
7379  * \brief Creates a graph of cell neighbors
7380  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7381  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7382  *  For example
7383  *  - index:  0 3 5 6 6
7384  *  - value:  1 2 3 2 3 3
7385  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7386  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7387  */
7388 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7389 {
7390   checkConnectivityFullyDefined();
7391
7392   int meshDim = this->getMeshDimension();
7393   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7394   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7395   this->getReverseNodalConnectivity(revConn,indexr);
7396   const int* indexr_ptr=indexr->begin();
7397   const int* revConn_ptr=revConn->begin();
7398
7399   const MEDCoupling::DataArrayInt* index;
7400   const MEDCoupling::DataArrayInt* conn;
7401   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7402   index=this->getNodalConnectivityIndex();
7403   int nbCells=this->getNumberOfCells();
7404   const int* index_ptr=index->begin();
7405   const int* conn_ptr=conn->begin();
7406
7407   //creating graph arcs (cell to cell relations)
7408   //arcs are stored in terms of (index,value) notation
7409   // 0 3 5 6 6
7410   // 1 2 3 2 3 3
7411   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7412   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7413
7414   //warning here one node have less than or equal effective number of cell with it
7415   //but cell could have more than effective nodes
7416   //because other equals nodes in other domain (with other global inode)
7417   std::vector <int> cell2cell_index(nbCells+1,0);
7418   std::vector <int> cell2cell;
7419   cell2cell.reserve(3*nbCells);
7420
7421   for (int icell=0; icell<nbCells;icell++)
7422     {
7423       std::map<int,int > counter;
7424       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7425         {
7426           int inode=conn_ptr[iconn];
7427           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7428             {
7429               int icell2=revConn_ptr[iconnr];
7430               std::map<int,int>::iterator iter=counter.find(icell2);
7431               if (iter!=counter.end()) (iter->second)++;
7432               else counter.insert(std::make_pair(icell2,1));
7433             }
7434         }
7435       for (std::map<int,int>::const_iterator iter=counter.begin();
7436            iter!=counter.end(); iter++)
7437         if (iter->second >= meshDim)
7438           {
7439             cell2cell_index[icell+1]++;
7440             cell2cell.push_back(iter->first);
7441           }
7442     }
7443   indexr->decrRef();
7444   revConn->decrRef();
7445   cell2cell_index[0]=0;
7446   for (int icell=0; icell<nbCells;icell++)
7447     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7448
7449   //filling up index and value to create skylinearray structure
7450   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7451   return array;
7452 }
7453
7454
7455 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7456 {
7457   int nbOfCells=getNumberOfCells();
7458   if(nbOfCells<=0)
7459     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7460   ofs << "  <" << getVTKDataSetType() << ">\n";
7461   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7462   ofs << "      <PointData>\n" << pointData << std::endl;
7463   ofs << "      </PointData>\n";
7464   ofs << "      <CellData>\n" << cellData << std::endl;
7465   ofs << "      </CellData>\n";
7466   ofs << "      <Points>\n";
7467   if(getSpaceDimension()==3)
7468     _coords->writeVTK(ofs,8,"Points",byteData);
7469   else
7470     {
7471       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7472       coo->writeVTK(ofs,8,"Points",byteData);
7473     }
7474   ofs << "      </Points>\n";
7475   ofs << "      <Cells>\n";
7476   const int *cPtr=_nodal_connec->begin();
7477   const int *cIPtr=_nodal_connec_index->begin();
7478   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7479   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7480   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7481   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7482   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7483   int szFaceOffsets=0,szConn=0;
7484   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7485     {
7486       *w2=cPtr[cIPtr[i]];
7487       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7488         {
7489           *w1=-1;
7490           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7491           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7492         }
7493       else
7494         {
7495           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7496           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7497           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7498           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7499           w4=std::copy(c.begin(),c.end(),w4);
7500         }
7501     }
7502   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7503   types->writeVTK(ofs,8,"UInt8","types",byteData);
7504   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7505   if(szFaceOffsets!=0)
7506     {//presence of Polyhedra
7507       connectivity->reAlloc(szConn);
7508       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7509       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7510       w1=faces->getPointer();
7511       for(int i=0;i<nbOfCells;i++)
7512         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7513           {
7514             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7515             *w1++=nbFaces;
7516             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7517             for(int j=0;j<nbFaces;j++)
7518               {
7519                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7520                 *w1++=(int)std::distance(w6,w5);
7521                 w1=std::copy(w6,w5,w1);
7522                 w6=w5+1;
7523               }
7524           }
7525       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7526     }
7527   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7528   ofs << "      </Cells>\n";
7529   ofs << "    </Piece>\n";
7530   ofs << "  </" << getVTKDataSetType() << ">\n";
7531 }
7532
7533 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7534 {
7535   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7536   if(_mesh_dim==-2)
7537     { stream << " Not set !"; return ; }
7538   stream << " Mesh dimension : " << _mesh_dim << ".";
7539   if(_mesh_dim==-1)
7540     return ;
7541   if(!_coords)
7542     { stream << " No coordinates set !"; return ; }
7543   if(!_coords->isAllocated())
7544     { stream << " Coordinates set but not allocated !"; return ; }
7545   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7546   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7547   if(!_nodal_connec_index)
7548     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7549   if(!_nodal_connec_index->isAllocated())
7550     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7551   int lgth=_nodal_connec_index->getNumberOfTuples();
7552   int cpt=_nodal_connec_index->getNumberOfComponents();
7553   if(cpt!=1 || lgth<1)
7554     return ;
7555   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7556 }
7557
7558 std::string MEDCouplingUMesh::getVTKDataSetType() const
7559 {
7560   return std::string("UnstructuredGrid");
7561 }
7562
7563 std::string MEDCouplingUMesh::getVTKFileExtension() const
7564 {
7565   return std::string("vtu");
7566 }
7567
7568
7569
7570 /**
7571  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7572  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7573  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7574  * The caller is to deal with the resulting DataArrayInt.
7575  *  \throw If the coordinate array is not set.
7576  *  \throw If the nodal connectivity of the cells is not defined.
7577  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7578  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7579  *
7580  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7581  */
7582 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7583 {
7584   checkFullyDefined();
7585   if(getMeshDimension()!=1)
7586     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7587
7588   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7589   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7590   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7591   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7592   const int *d(_d->begin()), *dI(_dI->begin());
7593   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7594   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7595   const int * dsi(_dsi->begin());
7596   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7597   m_points=0;
7598   if (dsii->getNumberOfTuples())
7599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7600
7601   int nc(getNumberOfCells());
7602   MCAuto<DataArrayInt> result(DataArrayInt::New());
7603   result->alloc(nc,1);
7604
7605   // set of edges not used so far
7606   std::set<int> edgeSet;
7607   for (int i=0; i<nc; edgeSet.insert(i), i++);
7608
7609   int startSeg=0;
7610   int newIdx=0;
7611   // while we have points with only one neighbor segments
7612   do
7613     {
7614       std::list<int> linePiece;
7615       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7616       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7617         {
7618           // Fill the list forward (resp. backward) from the start segment:
7619           int activeSeg = startSeg;
7620           int prevPointId = -20;
7621           int ptId;
7622           while (!edgeSet.empty())
7623             {
7624               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7625                 {
7626                   if (direction==0)
7627                     linePiece.push_back(activeSeg);
7628                   else
7629                     linePiece.push_front(activeSeg);
7630                   edgeSet.erase(activeSeg);
7631                 }
7632
7633               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7634               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7635               if (dsi[ptId] == 1) // hitting the end of the line
7636                 break;
7637               prevPointId = ptId;
7638               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7639               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7640             }
7641         }
7642       // Done, save final piece into DA:
7643       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7644       newIdx += linePiece.size();
7645
7646       // identify next valid start segment (one which is not consumed)
7647       if(!edgeSet.empty())
7648         startSeg = *(edgeSet.begin());
7649     }
7650   while (!edgeSet.empty());
7651   return result.retn();
7652 }
7653
7654 /**
7655  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7656  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7657  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7658  * a minimal creation of new nodes is wanted.
7659  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7660  * nodes if a SEG3 is split without information of middle.
7661  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7662  * avoid to have a non conform mesh.
7663  *
7664  * \return int - the number of new nodes created (in most of cases 0).
7665  * 
7666  * \throw If \a this is not coherent.
7667  * \throw If \a this has not spaceDim equal to 2.
7668  * \throw If \a this has not meshDim equal to 2.
7669  * \throw If some subcells needed to be split are orphan.
7670  * \sa MEDCouplingUMesh::conformize2D
7671  */
7672 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7673 {
7674   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7675     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7676   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7677   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7678     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7679   if(midOpt==0 && midOptI==0)
7680     {
7681       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7682       return 0;
7683     }
7684   else if(midOpt!=0 && midOptI!=0)
7685     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7686   else
7687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7688 }
7689
7690 /*!
7691  * 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
7692  * 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
7693  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7694  * 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
7695  * 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.
7696  * 
7697  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7698  */
7699 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7700 {
7701   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7702   if(sz>=4)
7703     {
7704       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7705       if(cm.getDimension()==2)
7706         {
7707           const int *node=nodalConnBg+1;
7708           int startNode=*node++;
7709           double refX=coords[2*startNode];
7710           for(;node!=nodalConnEnd;node++)
7711             {
7712               if(coords[2*(*node)]<refX)
7713                 {
7714                   startNode=*node;
7715                   refX=coords[2*startNode];
7716                 }
7717             }
7718           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7719           refX=1e300;
7720           double tmp1;
7721           double tmp2[2];
7722           double angle0=-M_PI/2;
7723           //
7724           int nextNode=-1;
7725           int prevNode=-1;
7726           double resRef;
7727           double angleNext=0.;
7728           while(nextNode!=startNode)
7729             {
7730               nextNode=-1;
7731               resRef=1e300;
7732               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7733                 {
7734                   if(*node!=tmpOut.back() && *node!=prevNode)
7735                     {
7736                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7737                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7738                       double res;
7739                       if(angleM<=angle0)
7740                         res=angle0-angleM;
7741                       else
7742                         res=angle0-angleM+2.*M_PI;
7743                       if(res<resRef)
7744                         {
7745                           nextNode=*node;
7746                           resRef=res;
7747                           angleNext=angleM;
7748                         }
7749                     }
7750                 }
7751               if(nextNode!=startNode)
7752                 {
7753                   angle0=angleNext-M_PI;
7754                   if(angle0<-M_PI)
7755                     angle0+=2*M_PI;
7756                   prevNode=tmpOut.back();
7757                   tmpOut.push_back(nextNode);
7758                 }
7759             }
7760           std::vector<int> tmp3(2*(sz-1));
7761           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7762           std::copy(nodalConnBg+1,nodalConnEnd,it);
7763           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7764             {
7765               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7766               return false;
7767             }
7768           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7769             {
7770               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7771               return false;
7772             }
7773           else
7774             {
7775               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7776               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7777               return true;
7778             }
7779         }
7780       else
7781         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7782     }
7783   else
7784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7785 }
7786
7787 /*!
7788  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7789  * 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.
7790  * 
7791  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7792  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7793  * \param [in,out] arr array in which the remove operation will be done.
7794  * \param [in,out] arrIndx array in the remove operation will modify
7795  * \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])
7796  * \return true if \b arr and \b arrIndx have been modified, false if not.
7797  */
7798 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7799 {
7800   if(!arrIndx || !arr)
7801     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7802   if(offsetForRemoval<0)
7803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7804   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7805   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7806   int *arrIPtr=arrIndx->getPointer();
7807   *arrIPtr++=0;
7808   int previousArrI=0;
7809   const int *arrPtr=arr->begin();
7810   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7811   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7812     {
7813       if(*arrIPtr-previousArrI>offsetForRemoval)
7814         {
7815           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7816             {
7817               if(s.find(*work)==s.end())
7818                 arrOut.push_back(*work);
7819             }
7820         }
7821       previousArrI=*arrIPtr;
7822       *arrIPtr=(int)arrOut.size();
7823     }
7824   if(arr->getNumberOfTuples()==arrOut.size())
7825     return false;
7826   arr->alloc((int)arrOut.size(),1);
7827   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7828   return true;
7829 }
7830
7831 /*!
7832  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7833  * (\ref numbering-indirect).
7834  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7835  * The selection of extraction is done standardly in new2old format.
7836  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7837  *
7838  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7839  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7840  * \param [in] arrIn arr origin array from which the extraction will be done.
7841  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7842  * \param [out] arrOut the resulting array
7843  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7844  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7845  */
7846 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7847                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7848 {
7849   if(!arrIn || !arrIndxIn)
7850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7851   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7852   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7854   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7855   const int *arrInPtr=arrIn->begin();
7856   const int *arrIndxPtr=arrIndxIn->begin();
7857   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7858   if(nbOfGrps<0)
7859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7860   int maxSizeOfArr=arrIn->getNumberOfTuples();
7861   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7862   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7863   arrIo->alloc((int)(sz+1),1);
7864   const int *idsIt=idsOfSelectBg;
7865   int *work=arrIo->getPointer();
7866   *work++=0;
7867   int lgth=0;
7868   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7869     {
7870       if(*idsIt>=0 && *idsIt<nbOfGrps)
7871         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7872       else
7873         {
7874           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7875           throw INTERP_KERNEL::Exception(oss.str());
7876         }
7877       if(lgth>=work[-1])
7878         *work=lgth;
7879       else
7880         {
7881           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7882           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7883           throw INTERP_KERNEL::Exception(oss.str());
7884         }
7885     }
7886   arro->alloc(lgth,1);
7887   work=arro->getPointer();
7888   idsIt=idsOfSelectBg;
7889   for(std::size_t i=0;i<sz;i++,idsIt++)
7890     {
7891       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7892         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7893       else
7894         {
7895           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7896           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7897           throw INTERP_KERNEL::Exception(oss.str());
7898         }
7899     }
7900   arrOut=arro.retn();
7901   arrIndexOut=arrIo.retn();
7902 }
7903
7904 /*!
7905  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7906  * (\ref numbering-indirect).
7907  * 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 ).
7908  * The selection of extraction is done standardly in new2old format.
7909  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7910  *
7911  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7912  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7913  * \param [in] idsOfSelectStep
7914  * \param [in] arrIn arr origin array from which the extraction will be done.
7915  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7916  * \param [out] arrOut the resulting array
7917  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7918  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7919  */
7920 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7921                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7922 {
7923   if(!arrIn || !arrIndxIn)
7924     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7925   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7926   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7927     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7928   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7929   const int *arrInPtr=arrIn->begin();
7930   const int *arrIndxPtr=arrIndxIn->begin();
7931   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7932   if(nbOfGrps<0)
7933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7934   int maxSizeOfArr=arrIn->getNumberOfTuples();
7935   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7936   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7937   arrIo->alloc((int)(sz+1),1);
7938   int idsIt=idsOfSelectStart;
7939   int *work=arrIo->getPointer();
7940   *work++=0;
7941   int lgth=0;
7942   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7943     {
7944       if(idsIt>=0 && idsIt<nbOfGrps)
7945         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7946       else
7947         {
7948           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7949           throw INTERP_KERNEL::Exception(oss.str());
7950         }
7951       if(lgth>=work[-1])
7952         *work=lgth;
7953       else
7954         {
7955           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7956           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7957           throw INTERP_KERNEL::Exception(oss.str());
7958         }
7959     }
7960   arro->alloc(lgth,1);
7961   work=arro->getPointer();
7962   idsIt=idsOfSelectStart;
7963   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7964     {
7965       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7966         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
7967       else
7968         {
7969           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7970           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7971           throw INTERP_KERNEL::Exception(oss.str());
7972         }
7973     }
7974   arrOut=arro.retn();
7975   arrIndexOut=arrIo.retn();
7976 }
7977
7978 /*!
7979  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7980  * 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
7981  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7982  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
7983  *
7984  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7985  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7986  * \param [in] arrIn arr origin array from which the extraction will be done.
7987  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7988  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7989  * \param [in] srcArrIndex index array of \b srcArr
7990  * \param [out] arrOut the resulting array
7991  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7992  * 
7993  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7994  */
7995 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7996                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7997                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7998 {
7999   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8000     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8001   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8002   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8003   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8004   std::vector<bool> v(nbOfTuples,true);
8005   int offset=0;
8006   const int *arrIndxInPtr=arrIndxIn->begin();
8007   const int *srcArrIndexPtr=srcArrIndex->begin();
8008   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8009     {
8010       if(*it>=0 && *it<nbOfTuples)
8011         {
8012           v[*it]=false;
8013           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8014         }
8015       else
8016         {
8017           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8018           throw INTERP_KERNEL::Exception(oss.str());
8019         }
8020     }
8021   srcArrIndexPtr=srcArrIndex->begin();
8022   arrIo->alloc(nbOfTuples+1,1);
8023   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8024   const int *arrInPtr=arrIn->begin();
8025   const int *srcArrPtr=srcArr->begin();
8026   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8027   int *arroPtr=arro->getPointer();
8028   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8029     {
8030       if(v[ii])
8031         {
8032           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8033           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8034         }
8035       else
8036         {
8037           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8038           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8039           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8040         }
8041     }
8042   arrOut=arro.retn();
8043   arrIndexOut=arrIo.retn();
8044 }
8045
8046 /*!
8047  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8048  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
8049  *
8050  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8051  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8052  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8053  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8054  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8055  * \param [in] srcArrIndex index array of \b srcArr
8056  * 
8057  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8058  */
8059 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8060                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8061 {
8062   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8063     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8064   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8065   const int *arrIndxInPtr=arrIndxIn->begin();
8066   const int *srcArrIndexPtr=srcArrIndex->begin();
8067   int *arrInOutPtr=arrInOut->getPointer();
8068   const int *srcArrPtr=srcArr->begin();
8069   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8070     {
8071       if(*it>=0 && *it<nbOfTuples)
8072         {
8073           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8074             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8075           else
8076             {
8077               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] !";
8078               throw INTERP_KERNEL::Exception(oss.str());
8079             }
8080         }
8081       else
8082         {
8083           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8084           throw INTERP_KERNEL::Exception(oss.str());
8085         }
8086     }
8087 }
8088
8089 /*!
8090  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8091  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8092  * 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]].
8093  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8094  * A negative value in \b arrIn means that it is ignored.
8095  * 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.
8096  * 
8097  * \param [in] arrIn arr origin array from which the extraction will be done.
8098  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8099  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8100  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8101  */
8102 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8103 {
8104   int seed=0,nbOfDepthPeelingPerformed=0;
8105   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8106 }
8107
8108 /*!
8109  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8110  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8111  * 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]].
8112  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8113  * A negative value in \b arrIn means that it is ignored.
8114  * 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.
8115  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8116  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8117  * \param [in] arrIn arr origin array from which the extraction will be done.
8118  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8119  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8120  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8121  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8122  * \sa MEDCouplingUMesh::partitionBySpreadZone
8123  */
8124 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
8125 {
8126   nbOfDepthPeelingPerformed=0;
8127   if(!arrIndxIn)
8128     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8129   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8130   if(nbOfTuples<=0)
8131     {
8132       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8133       return ret;
8134     }
8135   //
8136   std::vector<bool> fetched(nbOfTuples,false);
8137   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8138 }
8139
8140
8141 /*!
8142  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8143  * 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
8144  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8145  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitly a result output arrays.
8146  *
8147  * \param [in] start begin of set of ids of the input extraction (included)
8148  * \param [in] end end of set of ids of the input extraction (excluded)
8149  * \param [in] step step of the set of ids in range mode.
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] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8153  * \param [in] srcArrIndex index array of \b srcArr
8154  * \param [out] arrOut the resulting array
8155  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8156  * 
8157  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8158  */
8159 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8160                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8161                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8162 {
8163   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
8165   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8166   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8167   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8168   int offset=0;
8169   const int *arrIndxInPtr=arrIndxIn->begin();
8170   const int *srcArrIndexPtr=srcArrIndex->begin();
8171   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
8172   int it=start;
8173   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8174     {
8175       if(it>=0 && it<nbOfTuples)
8176         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8177       else
8178         {
8179           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8180           throw INTERP_KERNEL::Exception(oss.str());
8181         }
8182     }
8183   srcArrIndexPtr=srcArrIndex->begin();
8184   arrIo->alloc(nbOfTuples+1,1);
8185   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8186   const int *arrInPtr=arrIn->begin();
8187   const int *srcArrPtr=srcArr->begin();
8188   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8189   int *arroPtr=arro->getPointer();
8190   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8191     {
8192       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8193       if(pos<0)
8194         {
8195           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8196           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8197         }
8198       else
8199         {
8200           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8201           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8202         }
8203     }
8204   arrOut=arro.retn();
8205   arrIndexOut=arrIo.retn();
8206 }
8207
8208 /*!
8209  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8210  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignment do not modify the index in \b arrIndxIn.
8211  *
8212  * \param [in] start begin of set of ids of the input extraction (included)
8213  * \param [in] end end of set of ids of the input extraction (excluded)
8214  * \param [in] step step of the set of ids in range mode.
8215  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8216  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8217  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8218  * \param [in] srcArrIndex index array of \b srcArr
8219  * 
8220  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8221  */
8222 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8223                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8224 {
8225   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8227   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8228   const int *arrIndxInPtr=arrIndxIn->begin();
8229   const int *srcArrIndexPtr=srcArrIndex->begin();
8230   int *arrInOutPtr=arrInOut->getPointer();
8231   const int *srcArrPtr=srcArr->begin();
8232   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8233   int it=start;
8234   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8235     {
8236       if(it>=0 && it<nbOfTuples)
8237         {
8238           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8239             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8240           else
8241             {
8242               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8243               throw INTERP_KERNEL::Exception(oss.str());
8244             }
8245         }
8246       else
8247         {
8248           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8249           throw INTERP_KERNEL::Exception(oss.str());
8250         }
8251     }
8252 }
8253
8254 /*!
8255  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8256  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8257  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8258  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8259  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8260  * 
8261  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8262  */
8263 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8264 {
8265   checkFullyDefined();
8266   int mdim=getMeshDimension();
8267   int spaceDim=getSpaceDimension();
8268   if(mdim!=spaceDim)
8269     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8270   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8271   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8272   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8273   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8274   ret->setCoords(getCoords());
8275   ret->allocateCells((int)partition.size());
8276   //
8277   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8278     {
8279       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8280       MCAuto<DataArrayInt> cell;
8281       switch(mdim)
8282       {
8283         case 2:
8284           cell=tmp->buildUnionOf2DMesh();
8285           break;
8286         case 3:
8287           cell=tmp->buildUnionOf3DMesh();
8288           break;
8289         default:
8290           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8291       }
8292
8293       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8294     }
8295   //
8296   ret->finishInsertingCells();
8297   return ret.retn();
8298 }
8299
8300 /*!
8301  * This method partitions \b this into contiguous zone.
8302  * This method only needs a well defined connectivity. Coordinates are not considered here.
8303  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8304  */
8305 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8306 {
8307   DataArrayInt *neigh=0,*neighI=0;
8308   computeNeighborsOfCells(neigh,neighI);
8309   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8310   return PartitionBySpreadZone(neighAuto,neighIAuto);
8311 }
8312
8313 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8314 {
8315   if(!arrIn || !arrIndxIn)
8316     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8317   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8318   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8319   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8320     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8321   int nbOfCellsCur(nbOfTuples-1);
8322   std::vector<DataArrayInt *> ret;
8323   if(nbOfCellsCur<=0)
8324     return ret;
8325   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8326   std::vector< MCAuto<DataArrayInt> > ret2;
8327   int seed=0;
8328   while(seed<nbOfCellsCur)
8329     {
8330       int nbOfPeelPerformed=0;
8331       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8332       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8333     }
8334   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8335     ret.push_back((*it).retn());
8336   return ret;
8337 }
8338
8339 /*!
8340  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8341  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8342  *
8343  * \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.
8344  * \return a newly allocated DataArrayInt to be managed by the caller.
8345  * \throw In case of \a code has not the right format (typically of size 3*n)
8346  */
8347 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8348 {
8349   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8350   std::size_t nb=code.size()/3;
8351   if(code.size()%3!=0)
8352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8353   ret->alloc((int)nb,2);
8354   int *retPtr=ret->getPointer();
8355   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8356     {
8357       retPtr[0]=code[3*i+2];
8358       retPtr[1]=code[3*i+2]+code[3*i+1];
8359     }
8360   return ret.retn();
8361 }
8362
8363 /*!
8364  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8365  * All cells in \a this are expected to be linear 3D cells.
8366  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8367  * It leads to an increase to number of cells.
8368  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8369  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8370  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8371  *
8372  * \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.
8373  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8374  * \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. 
8375  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8376  *          an id of old cell producing it. The caller is to delete this array using
8377  *         decrRef() as it is no more needed.
8378  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8379  *
8380  * \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
8381  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8382  * 
8383  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8384  * \throw If \a this is not fully constituted with linear 3D cells.
8385  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8386  */
8387 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8388 {
8389   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8390   checkConnectivityFullyDefined();
8391   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8393   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8394   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8395   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8396   int *retPt(ret->getPointer());
8397   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8398   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8399   const int *oldc(_nodal_connec->begin());
8400   const int *oldci(_nodal_connec_index->begin());
8401   const double *coords(_coords->begin());
8402   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8403     {
8404       std::vector<int> a; std::vector<double> b;
8405       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8406       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8407       const int *aa(&a[0]);
8408       if(!b.empty())
8409         {
8410           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8411             if(*it<0)
8412               *it=(-(*(it))-1+nbNodes);
8413           addPts->insertAtTheEnd(b.begin(),b.end());
8414           nbNodes+=(int)b.size()/3;
8415         }
8416       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8417         newConn->insertAtTheEnd(aa,aa+4);
8418     }
8419   if(!addPts->empty())
8420     {
8421       addPts->rearrange(3);
8422       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8423       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8424       ret0->setCoords(addPts);
8425     }
8426   else
8427     {
8428       nbOfAdditionalPoints=0;
8429       ret0->setCoords(getCoords());
8430     }
8431   ret0->setNodalConnectivity(newConn);
8432   //
8433   ret->computeOffsetsFull();
8434   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8435   return ret0.retn();
8436 }
8437
8438 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8439     _own_cell(true),_cell_id(-1),_nb_cell(0)
8440 {
8441   if(mesh)
8442     {
8443       mesh->incrRef();
8444       _nb_cell=mesh->getNumberOfCells();
8445     }
8446 }
8447
8448 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8449 {
8450   if(_mesh)
8451     _mesh->decrRef();
8452   if(_own_cell)
8453     delete _cell;
8454 }
8455
8456 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8457     _own_cell(false),_cell_id(bg-1),
8458     _nb_cell(end)
8459 {
8460   if(mesh)
8461     mesh->incrRef();
8462 }
8463
8464 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8465 {
8466   _cell_id++;
8467   if(_cell_id<_nb_cell)
8468     {
8469       _cell->next();
8470       return _cell;
8471     }
8472   else
8473     return 0;
8474 }
8475
8476 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8477 {
8478   if(_mesh)
8479     _mesh->incrRef();
8480 }
8481
8482 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8483 {
8484   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8485 }
8486
8487 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8488 {
8489   if(_mesh)
8490     _mesh->decrRef();
8491 }
8492
8493 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8494     _itc(itc),
8495     _bg(bg),_end(end)
8496 {
8497   if(_mesh)
8498     _mesh->incrRef();
8499 }
8500
8501 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8502 {
8503   if(_mesh)
8504     _mesh->decrRef();
8505 }
8506
8507 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8508 {
8509   return _type;
8510 }
8511
8512 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8513 {
8514   return _end-_bg;
8515 }
8516
8517 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8518 {
8519   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8520 }
8521
8522 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8523 {
8524   if(mesh)
8525     {
8526       mesh->incrRef();
8527       _nb_cell=mesh->getNumberOfCells();
8528     }
8529 }
8530
8531 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8532 {
8533   if(_mesh)
8534     _mesh->decrRef();
8535   delete _cell;
8536 }
8537
8538 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8539 {
8540   const int *c=_mesh->getNodalConnectivity()->begin();
8541   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8542   if(_cell_id<_nb_cell)
8543     {
8544       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8545       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8546       int startId=_cell_id;
8547       _cell_id+=nbOfElems;
8548       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8549     }
8550   else
8551     return 0;
8552 }
8553
8554 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8555 {
8556   if(mesh)
8557     {
8558       _conn=mesh->getNodalConnectivity()->getPointer();
8559       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8560     }
8561 }
8562
8563 void MEDCouplingUMeshCell::next()
8564 {
8565   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8566     {
8567       _conn+=_conn_lgth;
8568       _conn_indx++;
8569     }
8570   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8571 }
8572
8573 std::string MEDCouplingUMeshCell::repr() const
8574 {
8575   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8576     {
8577       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8578       oss << " : ";
8579       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8580       return oss.str();
8581     }
8582   else
8583     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8584 }
8585
8586 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8587 {
8588   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8589     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8590   else
8591     return INTERP_KERNEL::NORM_ERROR;
8592 }
8593
8594 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8595 {
8596   lgth=_conn_lgth;
8597   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8598     return _conn;
8599   else
8600     return 0;
8601 }