Salome HOME
UMesh.computeEnlargedNeighborsOfNodes
[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 (CEA/DEN)
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 "MEDCouplingUMesh_internal.hxx"
45
46 #include <sstream>
47 #include <fstream>
48 #include <numeric>
49 #include <cstring>
50 #include <limits>
51 #include <list>
52
53 using namespace MEDCoupling;
54
55 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
56
57 /// @cond INTERNAL
58 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
59 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,-1,-1,25,42,36,4};
60 /// @endcond
61
62 MEDCouplingUMesh *MEDCouplingUMesh::New()
63 {
64   return new MEDCouplingUMesh;
65 }
66
67 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
68 {
69   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
70   ret->setName(meshName);
71   ret->setMeshDimension(meshDim);
72   return ret;
73 }
74
75 /*!
76  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
77  * between \a this and the new mesh.
78  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
79  *          delete this mesh using decrRef() as it is no more needed. 
80  */
81 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
82 {
83   return clone(true);
84 }
85
86
87 /*!
88  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
89  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
90  * this mesh are shared by the new mesh.
91  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
92  *          delete this mesh using decrRef() as it is no more needed. 
93  */
94 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
95 {
96   return new MEDCouplingUMesh(*this,recDeepCpy);
97 }
98
99 /*!
100  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
101  * The coordinates are shared between \a this and the returned instance.
102  * 
103  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
104  * \sa MEDCouplingUMesh::deepCopy
105  */
106 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
107 {
108   checkConnectivityFullyDefined();
109   MCAuto<MEDCouplingUMesh> ret=clone(false);
110   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
111   ret->setConnectivity(c,ci);
112   return ret.retn();
113 }
114
115 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
116 {
117   if(!other)
118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
119   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
120   if(!otherC)
121     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
122   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
123   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
124 }
125
126 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
127 {
128   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
129   return ret;
130 }
131
132 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
133 {
134   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
135   ret.push_back(_nodal_connec);
136   ret.push_back(_nodal_connec_index);
137   return ret;
138 }
139
140 void MEDCouplingUMesh::updateTime() const
141 {
142   MEDCouplingPointSet::updateTime();
143   if(_nodal_connec)
144     {
145       updateTimeWith(*_nodal_connec);
146     }
147   if(_nodal_connec_index)
148     {
149       updateTimeWith(*_nodal_connec_index);
150     }
151 }
152
153 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
154 {
155 }
156
157 /*!
158  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
159  * then \a this mesh is most probably is writable, exchangeable and available for most
160  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
161  * this method to check that all is in order with \a this mesh.
162  *  \throw If the mesh dimension is not set.
163  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
164  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
165  *  \throw If the connectivity data array has more than one component.
166  *  \throw If the connectivity data array has a named component.
167  *  \throw If the connectivity index data array has more than one component.
168  *  \throw If the connectivity index data array has a named component.
169  */
170 void MEDCouplingUMesh::checkConsistencyLight() const
171 {
172   if(_mesh_dim<-1)
173     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
174   if(_mesh_dim!=-1)
175     MEDCouplingPointSet::checkConsistencyLight();
176   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
177     {
178       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
179         {
180           std::ostringstream message;
181           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
182           throw INTERP_KERNEL::Exception(message.str().c_str());
183         }
184     }
185   if(_nodal_connec)
186     {
187       if(_nodal_connec->getNumberOfComponents()!=1)
188         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
189       if(_nodal_connec->getInfoOnComponent(0)!="")
190         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
191     }
192   else
193     if(_mesh_dim!=-1)
194       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
195   if(_nodal_connec_index)
196     {
197       if(_nodal_connec_index->getNumberOfComponents()!=1)
198         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
199       if(_nodal_connec_index->getInfoOnComponent(0)!="")
200         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
201     }
202   else
203     if(_mesh_dim!=-1)
204       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
205 }
206
207 /*!
208  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
209  * then \a this mesh is most probably is writable, exchangeable and available for all
210  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
211  * method thoroughly checks the nodal connectivity.
212  *  \param [in] eps - a not used parameter.
213  *  \throw If the mesh dimension is not set.
214  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
215  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
216  *  \throw If the connectivity data array has more than one component.
217  *  \throw If the connectivity data array has a named component.
218  *  \throw If the connectivity index data array has more than one component.
219  *  \throw If the connectivity index data array has a named component.
220  *  \throw If number of nodes defining an element does not correspond to the type of element.
221  *  \throw If the nodal connectivity includes an invalid node id.
222  */
223 void MEDCouplingUMesh::checkConsistency(double eps) const
224 {
225   checkConsistencyLight();
226   if(_mesh_dim==-1)
227     return ;
228   int meshDim=getMeshDimension();
229   int nbOfNodes=getNumberOfNodes();
230   int nbOfCells=getNumberOfCells();
231   const int *ptr=_nodal_connec->getConstPointer();
232   const int *ptrI=_nodal_connec_index->getConstPointer();
233   for(int i=0;i<nbOfCells;i++)
234     {
235       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
236       if((int)cm.getDimension()!=meshDim)
237         {
238           std::ostringstream oss;
239           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
240           throw INTERP_KERNEL::Exception(oss.str());
241         }
242       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
243       if(!cm.isDynamic())
244         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
245           {
246             std::ostringstream oss;
247             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
248             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
249             throw INTERP_KERNEL::Exception(oss.str());
250           }
251       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
252         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
253           {
254             std::ostringstream oss;
255             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
256             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
257             throw INTERP_KERNEL::Exception(oss.str());
258           }
259       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
260         {
261           int nodeId=*w;
262           if(nodeId>=0)
263             {
264               if(nodeId>=nbOfNodes)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
267                   throw INTERP_KERNEL::Exception(oss.str());
268                 }
269             }
270           else if(nodeId<-1)
271             {
272               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
273               throw INTERP_KERNEL::Exception(oss.str());
274             }
275           else
276             {
277               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
278                 {
279                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
280                   throw INTERP_KERNEL::Exception(oss.str());
281                 }
282             }
283         }
284     }
285 }
286
287 /*!
288  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
289  * elements contained in the mesh. For more info on the mesh dimension see
290  * \ref MEDCouplingUMeshPage.
291  *  \param [in] meshDim - a new mesh dimension.
292  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
293  */
294 void MEDCouplingUMesh::setMeshDimension(int meshDim)
295 {
296   if(meshDim<-1 || meshDim>3)
297     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
298   _mesh_dim=meshDim;
299   declareAsNew();
300 }
301
302 /*!
303  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
304  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
305  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
306  *
307  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
308  *
309  *  \if ENABLE_EXAMPLES
310  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
311  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
312  *  \endif
313  */
314 void MEDCouplingUMesh::allocateCells(int nbOfCells)
315 {
316   if(nbOfCells<0)
317     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
318   if(_nodal_connec_index)
319     {
320       _nodal_connec_index->decrRef();
321     }
322   if(_nodal_connec)
323     {
324       _nodal_connec->decrRef();
325     }
326   _nodal_connec_index=DataArrayInt::New();
327   _nodal_connec_index->reserve(nbOfCells+1);
328   _nodal_connec_index->pushBackSilent(0);
329   _nodal_connec=DataArrayInt::New();
330   _nodal_connec->reserve(2*nbOfCells);
331   _types.clear();
332   declareAsNew();
333 }
334
335 /*!
336  * Appends a cell to the connectivity array. For deeper understanding what is
337  * happening see \ref MEDCouplingUMeshNodalConnectivity.
338  *  \param [in] type - type of cell to add.
339  *  \param [in] size - number of nodes constituting this cell.
340  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
341  * 
342  *  \if ENABLE_EXAMPLES
343  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
344  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
345  *  \endif
346  */
347 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
348 {
349   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
350   if(_nodal_connec_index==0)
351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
352   if((int)cm.getDimension()==_mesh_dim)
353     {
354       if(!cm.isDynamic())
355         if(size!=(int)cm.getNumberOfNodes())
356           {
357             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
358             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
359             throw INTERP_KERNEL::Exception(oss.str());
360           }
361       int idx=_nodal_connec_index->back();
362       int val=idx+size+1;
363       _nodal_connec_index->pushBackSilent(val);
364       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
365       _types.insert(type);
366     }
367   else
368     {
369       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
370       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
371       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
372       throw INTERP_KERNEL::Exception(oss.str());
373     }
374 }
375
376 /*!
377  * Compacts data arrays to release unused memory. This method is to be called after
378  * finishing cell insertion using \a this->insertNextCell().
379  * 
380  *  \if ENABLE_EXAMPLES
381  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
382  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
383  *  \endif
384  */
385 void MEDCouplingUMesh::finishInsertingCells()
386 {
387   _nodal_connec->pack();
388   _nodal_connec_index->pack();
389   _nodal_connec->declareAsNew();
390   _nodal_connec_index->declareAsNew();
391   updateTime();
392 }
393
394 /*!
395  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
396  * Useful for python users.
397  */
398 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
399 {
400   return new MEDCouplingUMeshCellIterator(this);
401 }
402
403 /*!
404  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
405  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
406  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
407  * Useful for python users.
408  */
409 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
410 {
411   if(!checkConsecutiveCellTypes())
412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
413   return new MEDCouplingUMeshCellByTypeEntry(this);
414 }
415
416 /*!
417  * Returns a set of all cell types available in \a this mesh.
418  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
419  * \warning this method does not throw any exception even if \a this is not defined.
420  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
421  */
422 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
423 {
424   return _types;
425 }
426
427 /*!
428  * This method returns the sorted list of geometric types in \a this.
429  * 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
430  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
431  *
432  * \throw if connectivity in \a this is not correctly defined.
433  *  
434  * \sa MEDCouplingMesh::getAllGeoTypes
435  */
436 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
437 {
438   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
439   checkConnectivityFullyDefined();
440   int nbOfCells(getNumberOfCells());
441   if(nbOfCells==0)
442     return ret;
443   if(getNodalConnectivityArrayLen()<1)
444     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
445   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
446   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
447   for(int i=1;i<nbOfCells;i++,ci++)
448     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
449       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
450   return ret;
451 }
452
453 /*!
454  * This method is a method that compares \a this and \a other.
455  * This method compares \b all attributes, even names and component names.
456  */
457 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
458 {
459   if(!other)
460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
461   std::ostringstream oss; oss.precision(15);
462   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
463   if(!otherC)
464     {
465       reason="mesh given in input is not castable in MEDCouplingUMesh !";
466       return false;
467     }
468   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
469     return false;
470   if(_mesh_dim!=otherC->_mesh_dim)
471     {
472       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
473       reason=oss.str();
474       return false;
475     }
476   if(_types!=otherC->_types)
477     {
478       oss << "umesh geometric type mismatch :\nThis geometric types are :";
479       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
480         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
481       oss << "\nOther geometric types are :";
482       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
483         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
484       reason=oss.str();
485       return false;
486     }
487   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
488     if(_nodal_connec==0 || otherC->_nodal_connec==0)
489       {
490         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
491         return false;
492       }
493   if(_nodal_connec!=otherC->_nodal_connec)
494     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
495       {
496         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
497         return false;
498       }
499   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
500     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
501       {
502         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
503         return false;
504       }
505   if(_nodal_connec_index!=otherC->_nodal_connec_index)
506     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
507       {
508         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
509         return false;
510       }
511   return true;
512 }
513
514 /*!
515  * Checks if data arrays of this mesh (node coordinates, nodal
516  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
517  * not considered.
518  *  \param [in] other - the mesh to compare with.
519  *  \param [in] prec - precision value used to compare node coordinates.
520  *  \return bool - \a true if the two meshes are same.
521  */
522 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
523 {
524   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
525   if(!otherC)
526     return false;
527   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
528     return false;
529   if(_mesh_dim!=otherC->_mesh_dim)
530     return false;
531   if(_types!=otherC->_types)
532     return false;
533   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
534     if(_nodal_connec==0 || otherC->_nodal_connec==0)
535       return false;
536   if(_nodal_connec!=otherC->_nodal_connec)
537     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
538       return false;
539   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
540     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
541       return false;
542   if(_nodal_connec_index!=otherC->_nodal_connec_index)
543     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
544       return false;
545   return true;
546 }
547
548 /*!
549  * Checks if \a this and \a other meshes are geometrically equivalent with high
550  * probability, else an exception is thrown. The meshes are considered equivalent if
551  * (1) meshes contain the same number of nodes and the same number of elements of the
552  * same types (2) three cells of the two meshes (first, last and middle) are based
553  * on coincident nodes (with a specified precision).
554  *  \param [in] other - the mesh to compare with.
555  *  \param [in] prec - the precision used to compare nodes of the two meshes.
556  *  \throw If the two meshes do not match.
557  */
558 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
559 {
560   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
561   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
562   if(!otherC)
563     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
564 }
565
566 /*!
567  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
568  * cells each node belongs to.
569  * \warning For speed reasons, this method does not check if node ids in the nodal
570  *          connectivity correspond to the size of node coordinates array.
571  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
572  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
573  *        dividing cell ids in \a revNodal into groups each referring to one
574  *        node. Its every element (except the last one) is an index pointing to the
575  *         first id of a group of cells. For example cells sharing the node #1 are 
576  *        described by following range of indices: 
577  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
578  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
579  *        Number of cells sharing the *i*-th node is
580  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
581  * \throw If the coordinates array is not set.
582  * \throw If the nodal connectivity of cells is not defined.
583  * 
584  * \if ENABLE_EXAMPLES
585  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
586  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
587  * \endif
588  */
589 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
590 {
591   checkFullyDefined();
592   int nbOfNodes(getNumberOfNodes());
593   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
594   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
595   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
596   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
597   int nbOfCells(getNumberOfCells()),nbOfEltsInRevNodal(0);
598   for(int eltId=0;eltId<nbOfCells;eltId++)
599     {
600       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
601       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
602         if(*iter>=0)//for polyhedrons
603           {
604             nbOfEltsInRevNodal++;
605             revNodalIndxPtr[(*iter)+1]++;
606           }
607     }
608   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
609   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
610   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
611   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
612   for(int eltId=0;eltId<nbOfCells;eltId++)
613     {
614       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
615       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
616       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
617         if(*iter>=0)//for polyhedrons
618           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
619     }
620 }
621
622 /*!
623  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
624  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
625  * describing correspondence between cells of \a this and the result meshes are
626  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
627  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
628  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
629  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
630  * \warning For speed reasons, this method does not check if node ids in the nodal
631  *          connectivity correspond to the size of node coordinates array.
632  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
633  *          to write this mesh to the MED file, its cells must be sorted using
634  *          sortCellsInMEDFileFrmt().
635  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
636  *         each cell of \a this mesh.
637  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
638  *        dividing cell ids in \a desc into groups each referring to one
639  *        cell of \a this mesh. Its every element (except the last one) is an index
640  *        pointing to the first id of a group of cells. For example cells of the
641  *        result mesh bounding the cell #1 of \a this mesh are described by following
642  *        range of indices:
643  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
644  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
645  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
646  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
647  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
648  *         by each cell of the result mesh.
649  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
650  *        in the result mesh,
651  *        dividing cell ids in \a revDesc into groups each referring to one
652  *        cell of the result mesh the same way as \a descIndx divides \a desc.
653  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
654  *        delete this mesh using decrRef() as it is no more needed.
655  *  \throw If the coordinates array is not set.
656  *  \throw If the nodal connectivity of cells is node defined.
657  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
658  *         revDescIndx == NULL.
659  * 
660  *  \if ENABLE_EXAMPLES
661  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
662  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
663  *  \endif
664  * \sa buildDescendingConnectivity2()
665  */
666 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
667 {
668   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
669 }
670
671 /*!
672  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
673  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
674  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
675  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
676  * \sa MEDCouplingUMesh::buildDescendingConnectivity
677  */
678 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
679 {
680   checkFullyDefined();
681   if(getMeshDimension()!=3)
682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
683   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
684 }
685
686 /*!
687  * 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.
688  * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
689  * 
690  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
691  */
692 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
693 {
694    checkFullyDefined();
695    switch(getMeshDimension())
696      {
697      case 2:
698        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
699      case 3:
700        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
701      default:
702        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
703      }
704 }
705
706 /*!
707  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
708  * this->getMeshDimension(), that bound cells of \a this mesh. In
709  * addition arrays describing correspondence between cells of \a this and the result
710  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
711  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
712  *  mesh. This method differs from buildDescendingConnectivity() in that apart
713  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
714  * result meshes. So a positive id means that order of nodes in corresponding cells
715  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
716  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
717  * i.e. cell ids are one-based.
718  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
719  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
720  * \warning For speed reasons, this method does not check if node ids in the nodal
721  *          connectivity correspond to the size of node coordinates array.
722  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
723  *          to write this mesh to the MED file, its cells must be sorted using
724  *          sortCellsInMEDFileFrmt().
725  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
726  *         each cell of \a this mesh.
727  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
728  *        dividing cell ids in \a desc into groups each referring to one
729  *        cell of \a this mesh. Its every element (except the last one) is an index
730  *        pointing to the first id of a group of cells. For example cells of the
731  *        result mesh bounding the cell #1 of \a this mesh are described by following
732  *        range of indices:
733  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
734  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
735  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
736  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
737  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
738  *         by each cell of the result mesh.
739  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
740  *        in the result mesh,
741  *        dividing cell ids in \a revDesc into groups each referring to one
742  *        cell of the result mesh the same way as \a descIndx divides \a desc.
743  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
744  *        shares the node coordinates array with \a this mesh. The caller is to
745  *        delete this mesh using decrRef() as it is no more needed.
746  *  \throw If the coordinates array is not set.
747  *  \throw If the nodal connectivity of cells is node defined.
748  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
749  *         revDescIndx == NULL.
750  * 
751  *  \if ENABLE_EXAMPLES
752  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
753  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
754  *  \endif
755  * \sa buildDescendingConnectivity()
756  */
757 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
758 {
759   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
760 }
761
762 /*!
763  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
764  * For speed reasons no check of this will be done. This method calls
765  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
766  * This method lists cell by cell in \b this which are its neighbors. To compute the result
767  * only connectivities are considered.
768  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
769  * The format of return is hence \ref numbering-indirect.
770  *
771  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
772  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
773  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
774  * is equal to the last values in \b neighborsIndx.
775  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
776  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
777  */
778 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
779 {
780   MCAuto<DataArrayInt> desc=DataArrayInt::New();
781   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
782   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
783   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
784   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
785   meshDM1=0;
786   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
787 }
788
789 void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayInt *nodeNeigh, const DataArrayInt *nodeNeighI, MCAuto<DataArrayInt>& cellNeigh, MCAuto<DataArrayInt>& cellNeighIndex) const
790 {
791   if(!nodeNeigh || !nodeNeighI)
792     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !");
793   checkConsistencyLight();
794   nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated();
795   nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh");
796   nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index");
797   nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length");
798   int nbCells(getNumberOfCells());
799   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin());
800   cellNeigh=DataArrayInt::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayInt::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0);
801   for(int i=0;i<nbCells;i++)
802     {
803       std::set<int> s;
804       for(const int *it=c+ci[i]+1;it!=c+ci[i+1];it++)
805         if(*it>=0)
806           s.insert(ne+nei[*it],ne+nei[*it+1]);
807       s.erase(i);
808       cellNeigh->insertAtTheEnd(s.begin(),s.end());
809       cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples());
810     }
811 }
812
813 /*!
814  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
815  * of MEDCouplingUMesh::computeNeighborsOfCells.
816  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
817  * typically the case to extract a set a neighbours,
818  * excluding a set of meshdim-1 cells in input descending connectivity.
819  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
820  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
821  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
822  * are considered.
823  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
824  *
825  * \param [in] desc descending connectivity array.
826  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
827  * \param [in] revDesc reverse descending connectivity array.
828  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
829  * \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
830  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
831  * \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.
832  */
833 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
834                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
835 {
836   if(!desc || !descIndx || !revDesc || !revDescIndx)
837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
838   const int *descPtr=desc->begin();
839   const int *descIPtr=descIndx->begin();
840   const int *revDescPtr=revDesc->begin();
841   const int *revDescIPtr=revDescIndx->begin();
842   //
843   int nbCells=descIndx->getNumberOfTuples()-1;
844   MCAuto<DataArrayInt> out0=DataArrayInt::New();
845   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
846   int *out1Ptr=out1->getPointer();
847   *out1Ptr++=0;
848   out0->reserve(desc->getNumberOfTuples());
849   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
850     {
851       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
852         {
853           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
854           s.erase(i);
855           out0->insertAtTheEnd(s.begin(),s.end());
856         }
857       *out1Ptr=out0->getNumberOfTuples();
858     }
859   neighbors=out0.retn();
860   neighborsIndx=out1.retn();
861 }
862
863 /*!
864  * Explodes \a this into edges whatever its dimension.
865  */
866 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::explodeIntoEdges(MCAuto<DataArrayInt>& desc, MCAuto<DataArrayInt>& descIndex, MCAuto<DataArrayInt>& revDesc, MCAuto<DataArrayInt>& revDescIndx) const
867 {
868   checkFullyDefined();
869   int mdim(getMeshDimension());
870   desc=DataArrayInt::New(); descIndex=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
871   MCAuto<MEDCouplingUMesh> mesh1D;
872   switch(mdim)
873   {
874     case 3:
875       {
876         mesh1D=explode3DMeshTo1D(desc,descIndex,revDesc,revDescIndx);
877         break;
878       }
879     case 2:
880       {
881         mesh1D=buildDescendingConnectivity(desc,descIndex,revDesc,revDescIndx);
882         break;
883       }
884     default:
885       {
886         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2] !");
887       }
888   }
889   return mesh1D;
890 }
891
892 /*!
893  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
894  * For speed reasons no check of this will be done. This method calls
895  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
896  * This method lists node by node in \b this which are its neighbors. To compute the result
897  * only connectivities are considered.
898  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
899  *
900  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
901  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
902  * parameter allows to select the right part in this array (\ref numbering-indirect).
903  * The number of tuples is equal to the last values in \b neighborsIndx.
904  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
905  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
906  * 
907  * \sa MEDCouplingUMesh::computeEnlargedNeighborsOfNodes
908  */
909 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
910 {
911   checkFullyDefined();
912   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
913   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
914   MCConstAuto<MEDCouplingUMesh> mesh1D;
915   switch(mdim)
916   {
917     case 3:
918       {
919         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
920         break;
921       }
922     case 2:
923       {
924         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
925         break;
926       }
927     case 1:
928       {
929         mesh1D.takeRef(this);
930         break;
931       }
932     default:
933       {
934         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
935       }
936   }
937   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
938   mesh1D->getReverseNodalConnectivity(desc,descIndx);
939   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
940   ret0->alloc(desc->getNumberOfTuples(),1);
941   int *r0Pt(ret0->getPointer());
942   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
943   for(int i=0;i<nbNodes;i++,rni++)
944     {
945       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
946         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
947     }
948   neighbors=ret0.retn();
949   neighborsIdx=descIndx.retn();
950 }
951
952 /*!
953  * 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.
954  * 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.
955  * This method is useful to find ghost cells of a part of a mesh with a code based on fields on nodes.
956  * 
957  * \sa MEDCouplingUMesh::computeNeighborsOfNodes
958  */
959 void MEDCouplingUMesh::computeEnlargedNeighborsOfNodes(MCAuto<DataArrayInt> &neighbors, MCAuto<DataArrayInt>& neighborsIdx) const
960 {
961   checkFullyDefined();
962   int nbOfNodes(getNumberOfNodes());
963   const int *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
964   int nbOfCells(getNumberOfCells());
965   std::vector< std::set<int> > st0(nbOfNodes);
966   for(int eltId=0;eltId<nbOfCells;eltId++)
967     {
968       const int *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
969       std::set<int> s(strtNdlConnOfCurCell,endNdlConnOfCurCell); s.erase(-1); //for polyhedrons
970       for(std::set<int>::const_iterator iter2=s.begin();iter2!=s.end();iter2++)
971         st0[*iter2].insert(s.begin(),s.end());
972     }
973   neighborsIdx=DataArrayInt::New(); neighborsIdx->alloc(nbOfNodes+1,1); neighborsIdx->setIJ(0,0,0);
974   {
975     int *neighIdx(neighborsIdx->getPointer());
976     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++)
977       neighIdx[1]=neighIdx[0]+(*it).size()-1;
978   }
979   neighbors=DataArrayInt::New(); neighbors->alloc(neighborsIdx->back(),1);
980   {
981     const int *neighIdx(neighborsIdx->begin());
982     int *neigh(neighbors->getPointer()),nodeId(0);
983     for(std::vector< std::set<int> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++,nodeId++)
984       {
985         std::set<int> s(*it); s.erase(nodeId);
986         std::copy(s.begin(),s.end(),neigh+*neighIdx);
987       }
988   }
989 }
990
991 /*!
992  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
993  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
994  * array of cell ids. Pay attention that after conversion all algorithms work slower
995  * with \a this mesh than before conversion. <br> If an exception is thrown during the
996  * conversion due presence of invalid ids in the array of cells to convert, as a
997  * result \a this mesh contains some already converted elements. In this case the 2D
998  * mesh remains valid but 3D mesh becomes \b inconsistent!
999  *  \warning This method can significantly modify the order of geometric types in \a this,
1000  *          hence, to write this mesh to the MED file, its cells must be sorted using
1001  *          sortCellsInMEDFileFrmt().
1002  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1003  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1004  *         cellIdsToConvertBg.
1005  *  \throw If the coordinates array is not set.
1006  *  \throw If the nodal connectivity of cells is node defined.
1007  *  \throw If dimension of \a this mesh is not either 2 or 3.
1008  *
1009  *  \if ENABLE_EXAMPLES
1010  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1011  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1012  *  \endif
1013  */
1014 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1015 {
1016   checkFullyDefined();
1017   int dim=getMeshDimension();
1018   if(dim<2 || dim>3)
1019     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1020   int nbOfCells(getNumberOfCells());
1021   if(dim==2)
1022     {
1023       const int *connIndex=_nodal_connec_index->begin();
1024       int *conn=_nodal_connec->getPointer();
1025       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1026         {
1027           if(*iter>=0 && *iter<nbOfCells)
1028             {
1029               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1030               if(!cm.isQuadratic())
1031                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1032               else
1033                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1034             }
1035           else
1036             {
1037               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1038               oss << " in range [0," << nbOfCells << ") !";
1039               throw INTERP_KERNEL::Exception(oss.str());
1040             }
1041         }
1042     }
1043   else
1044     {
1045       int *connIndex(_nodal_connec_index->getPointer());
1046       const int *connOld(_nodal_connec->getConstPointer());
1047       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1048       std::vector<bool> toBeDone(nbOfCells,false);
1049       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1050         {
1051           if(*iter>=0 && *iter<nbOfCells)
1052             toBeDone[*iter]=true;
1053           else
1054             {
1055               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1056               oss << " in range [0," << nbOfCells << ") !";
1057               throw INTERP_KERNEL::Exception(oss.str());
1058             }
1059         }
1060       for(int cellId=0;cellId<nbOfCells;cellId++)
1061         {
1062           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1063           int lgthOld(posP1-pos-1);
1064           if(toBeDone[cellId])
1065             {
1066               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1067               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1068               int *tmp(new int[nbOfFaces*lgthOld+1]);
1069               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1070               for(unsigned j=0;j<nbOfFaces;j++)
1071                 {
1072                   INTERP_KERNEL::NormalizedCellType type;
1073                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1074                   work+=offset;
1075                   *work++=-1;
1076                 }
1077               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1078               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1079               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1080               delete [] tmp;
1081             }
1082           else
1083             {
1084               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1085               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1086             }
1087         }
1088       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1089     }
1090   computeTypes();
1091 }
1092
1093 /*!
1094  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1095  * polyhedrons (if \a this is a 3D mesh).
1096  *  \warning As this method is purely for user-friendliness and no optimization is
1097  *          done to avoid construction of a useless vector, this method can be costly
1098  *          in memory.
1099  *  \throw If the coordinates array is not set.
1100  *  \throw If the nodal connectivity of cells is node defined.
1101  *  \throw If dimension of \a this mesh is not either 2 or 3.
1102  */
1103 void MEDCouplingUMesh::convertAllToPoly()
1104 {
1105   int nbOfCells=getNumberOfCells();
1106   std::vector<int> cellIds(nbOfCells);
1107   for(int i=0;i<nbOfCells;i++)
1108     cellIds[i]=i;
1109   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1110 }
1111
1112 /*!
1113  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1114  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1115  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1116  * base facet of the volume and the second half of nodes describes an opposite facet
1117  * having the same number of nodes as the base one. This method converts such
1118  * connectivity to a valid polyhedral format where connectivity of each facet is
1119  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1120  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1121  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1122  * a correct orientation of the first facet of a polyhedron, else orientation of a
1123  * corrected cell is reverse.<br>
1124  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1125  * it releases the user from boring description of polyhedra connectivity in the valid
1126  * format.
1127  *  \throw If \a this->getMeshDimension() != 3.
1128  *  \throw If \a this->getSpaceDimension() != 3.
1129  *  \throw If the nodal connectivity of cells is not defined.
1130  *  \throw If the coordinates array is not set.
1131  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1132  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1133  *
1134  *  \if ENABLE_EXAMPLES
1135  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1136  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1137  *  \endif
1138  */
1139 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1140 {
1141   checkFullyDefined();
1142   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1144   int nbOfCells=getNumberOfCells();
1145   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1146   newCi->alloc(nbOfCells+1,1);
1147   int *newci=newCi->getPointer();
1148   const int *ci=_nodal_connec_index->getConstPointer();
1149   const int *c=_nodal_connec->getConstPointer();
1150   newci[0]=0;
1151   for(int i=0;i<nbOfCells;i++)
1152     {
1153       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1154       if(type==INTERP_KERNEL::NORM_POLYHED)
1155         {
1156           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1157             {
1158               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1159               throw INTERP_KERNEL::Exception(oss.str());
1160             }
1161           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1162           if(n2%2!=0)
1163             {
1164               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 !";
1165               throw INTERP_KERNEL::Exception(oss.str());
1166             }
1167           int n1=(int)(n2/2);
1168           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)
1169         }
1170       else
1171         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1172     }
1173   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1174   newC->alloc(newci[nbOfCells],1);
1175   int *newc=newC->getPointer();
1176   for(int i=0;i<nbOfCells;i++)
1177     {
1178       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1179       if(type==INTERP_KERNEL::NORM_POLYHED)
1180         {
1181           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1182           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1183           *newc++=-1;
1184           for(std::size_t j=0;j<n1;j++)
1185             {
1186               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1187               newc[n1+5*j]=-1;
1188               newc[n1+5*j+1]=c[ci[i]+1+j];
1189               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1190               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1191               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1192             }
1193           newc+=n1*6;
1194         }
1195       else
1196         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1197     }
1198   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1199   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1200 }
1201
1202
1203 /*!
1204  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1205  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1206  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1207  *          to write this mesh to the MED file, its cells must be sorted using
1208  *          sortCellsInMEDFileFrmt().
1209  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1210  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1211  * \return \c true if at least one cell has been converted, \c false else. In the
1212  *         last case the nodal connectivity remains unchanged.
1213  * \throw If the coordinates array is not set.
1214  * \throw If the nodal connectivity of cells is not defined.
1215  * \throw If \a this->getMeshDimension() < 0.
1216  */
1217 bool MEDCouplingUMesh::unPolyze()
1218 {
1219   checkFullyDefined();
1220   int mdim=getMeshDimension();
1221   if(mdim<0)
1222     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1223   if(mdim<=1)
1224     return false;
1225   int nbOfCells=getNumberOfCells();
1226   if(nbOfCells<1)
1227     return false;
1228   int initMeshLgth=getNodalConnectivityArrayLen();
1229   int *conn=_nodal_connec->getPointer();
1230   int *index=_nodal_connec_index->getPointer();
1231   int posOfCurCell=0;
1232   int newPos=0;
1233   int lgthOfCurCell;
1234   bool ret=false;
1235   for(int i=0;i<nbOfCells;i++)
1236     {
1237       lgthOfCurCell=index[i+1]-posOfCurCell;
1238       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1239       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1240       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1241       int newLgth;
1242       if(cm.isDynamic())
1243         {
1244           switch(cm.getDimension())
1245           {
1246             case 2:
1247               {
1248                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1249                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1250                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1251                 break;
1252               }
1253             case 3:
1254               {
1255                 int nbOfFaces,lgthOfPolyhConn;
1256                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1257                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1258                 break;
1259               }
1260             case 1:
1261               {
1262                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1263                 break;
1264               }
1265           }
1266           ret=ret || (newType!=type);
1267           conn[newPos]=newType;
1268           newPos+=newLgth+1;
1269           posOfCurCell=index[i+1];
1270           index[i+1]=newPos;
1271         }
1272       else
1273         {
1274           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1275           newPos+=lgthOfCurCell;
1276           posOfCurCell+=lgthOfCurCell;
1277           index[i+1]=newPos;
1278         }
1279     }
1280   if(newPos!=initMeshLgth)
1281     _nodal_connec->reAlloc(newPos);
1282   if(ret)
1283     computeTypes();
1284   return ret;
1285 }
1286
1287 /*!
1288  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1289  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1290  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1291  *
1292  * \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 
1293  *             precision.
1294  */
1295 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1296 {
1297   checkFullyDefined();
1298   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1299     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1300   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1301   coords->recenterForMaxPrecision(eps);
1302   //
1303   int nbOfCells=getNumberOfCells();
1304   const int *conn=_nodal_connec->getConstPointer();
1305   const int *index=_nodal_connec_index->getConstPointer();
1306   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1307   connINew->alloc(nbOfCells+1,1);
1308   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1309   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1310   bool changed=false;
1311   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1312     {
1313       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1314         {
1315           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1316           changed=true;
1317         }
1318       else
1319         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1320       *connINewPtr=connNew->getNumberOfTuples();
1321     }
1322   if(changed)
1323     setConnectivity(connNew,connINew,false);
1324 }
1325
1326 /*!
1327  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1328  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1329  * the format of the returned DataArrayInt instance.
1330  * 
1331  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1332  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1333  */
1334 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1335 {
1336   checkConnectivityFullyDefined();
1337   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1338   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1339   std::vector<bool> retS(maxElt,false);
1340   computeNodeIdsAlg(retS);
1341   return DataArrayInt::BuildListOfSwitchedOn(retS);
1342 }
1343
1344 /*!
1345  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1346  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1347  */
1348 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1349 {
1350   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1351   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1352   for(int i=0;i<nbOfCells;i++)
1353     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1354       if(conn[j]>=0)
1355         {
1356           if(conn[j]<nbOfNodes)
1357             nodeIdsInUse[conn[j]]=true;
1358           else
1359             {
1360               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1361               throw INTERP_KERNEL::Exception(oss.str());
1362             }
1363         }
1364 }
1365
1366 /// @cond INTERNAL
1367
1368 struct MEDCouplingAccVisit
1369 {
1370   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1371   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1372   int _new_nb_of_nodes;
1373 };
1374
1375 /// @endcond
1376
1377 /*!
1378  * Finds nodes not used in any cell and returns an array giving a new id to every node
1379  * by excluding the unused nodes, for which the array holds -1. The result array is
1380  * a mapping in "Old to New" mode. 
1381  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1382  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1383  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1384  *          if the node is unused or a new id else. The caller is to delete this
1385  *          array using decrRef() as it is no more needed.  
1386  *  \throw If the coordinates array is not set.
1387  *  \throw If the nodal connectivity of cells is not defined.
1388  *  \throw If the nodal connectivity includes an invalid id.
1389  *
1390  *  \if ENABLE_EXAMPLES
1391  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1392  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1393  *  \endif
1394  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1395  */
1396 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1397 {
1398   nbrOfNodesInUse=-1;
1399   int nbOfNodes(getNumberOfNodes());
1400   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1401   ret->alloc(nbOfNodes,1);
1402   int *traducer=ret->getPointer();
1403   std::fill(traducer,traducer+nbOfNodes,-1);
1404   int nbOfCells=getNumberOfCells();
1405   const int *connIndex=_nodal_connec_index->getConstPointer();
1406   const int *conn=_nodal_connec->getConstPointer();
1407   for(int i=0;i<nbOfCells;i++)
1408     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1409       if(conn[j]>=0)
1410         {
1411           if(conn[j]<nbOfNodes)
1412             traducer[conn[j]]=1;
1413           else
1414             {
1415               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1416               throw INTERP_KERNEL::Exception(oss.str());
1417             }
1418         }
1419   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1420   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1421   return ret.retn();
1422 }
1423
1424 /*!
1425  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1426  * For each cell in \b this the number of nodes constituting cell is computed.
1427  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1428  * So for pohyhedrons some nodes can be counted several times in the returned result.
1429  * 
1430  * \return a newly allocated array
1431  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1432  */
1433 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1434 {
1435   checkConnectivityFullyDefined();
1436   int nbOfCells=getNumberOfCells();
1437   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1438   ret->alloc(nbOfCells,1);
1439   int *retPtr=ret->getPointer();
1440   const int *conn=getNodalConnectivity()->getConstPointer();
1441   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1442   for(int i=0;i<nbOfCells;i++,retPtr++)
1443     {
1444       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1445         *retPtr=connI[i+1]-connI[i]-1;
1446       else
1447         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1448     }
1449   return ret.retn();
1450 }
1451
1452 /*!
1453  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1454  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1455  *
1456  * \return DataArrayInt * - new object to be deallocated by the caller.
1457  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1458  */
1459 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1460 {
1461   checkConnectivityFullyDefined();
1462   int nbOfCells=getNumberOfCells();
1463   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1464   ret->alloc(nbOfCells,1);
1465   int *retPtr=ret->getPointer();
1466   const int *conn=getNodalConnectivity()->getConstPointer();
1467   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1468   for(int i=0;i<nbOfCells;i++,retPtr++)
1469     {
1470       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1471       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1472         *retPtr=(int)s.size();
1473       else
1474         {
1475           s.erase(-1);
1476           *retPtr=(int)s.size();
1477         }
1478     }
1479   return ret.retn();
1480 }
1481
1482 /*!
1483  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1484  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1485  * 
1486  * \return a newly allocated array
1487  */
1488 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1489 {
1490   checkConnectivityFullyDefined();
1491   int nbOfCells=getNumberOfCells();
1492   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1493   ret->alloc(nbOfCells,1);
1494   int *retPtr=ret->getPointer();
1495   const int *conn=getNodalConnectivity()->getConstPointer();
1496   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1497   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1498     {
1499       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1500       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1501     }
1502   return ret.retn();
1503 }
1504
1505 /*!
1506  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1507  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1508  * array mean that the corresponding old node is no more used. 
1509  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1510  *           this->getNumberOfNodes() before call of this method. The caller is to
1511  *           delete this array using decrRef() as it is no more needed. 
1512  *  \throw If the coordinates array is not set.
1513  *  \throw If the nodal connectivity of cells is not defined.
1514  *  \throw If the nodal connectivity includes an invalid id.
1515  *  \sa areAllNodesFetched
1516  *
1517  *  \if ENABLE_EXAMPLES
1518  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1519  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1520  *  \endif
1521  */
1522 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1523 {
1524   return MEDCouplingPointSet::zipCoordsTraducer();
1525 }
1526
1527 /*!
1528  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1529  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1530  */
1531 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1532 {
1533   switch(compType)
1534   {
1535     case 0:
1536       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1537     case 1:
1538       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1539     case 2:
1540       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1541     case 3:
1542       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1543     case 7:
1544       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1545   }
1546   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1547 }
1548
1549 /*!
1550  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1551  */
1552 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1553 {
1554   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1555     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1556   return 0;
1557 }
1558
1559 /*!
1560  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1561  */
1562 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1563 {
1564   int sz=connI[cell1+1]-connI[cell1];
1565   if(sz==connI[cell2+1]-connI[cell2])
1566     {
1567       if(conn[connI[cell1]]==conn[connI[cell2]])
1568         {
1569           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1570           unsigned dim=cm.getDimension();
1571           if(dim!=3)
1572             {
1573               if(dim!=1)
1574                 {
1575                   int sz1=2*(sz-1);
1576                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1577                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1578                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1579                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1580                   return work!=tmp+sz1?1:0;
1581                 }
1582               else
1583                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1584             }
1585           else
1586             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1587         }
1588     }
1589   return 0;
1590 }
1591
1592 /*!
1593  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1594  */
1595 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1596 {
1597   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1598     {
1599       if(conn[connI[cell1]]==conn[connI[cell2]])
1600         {
1601           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1602           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1603           return s1==s2?1:0;
1604         }
1605     }
1606   return 0;
1607 }
1608
1609 /*!
1610  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1611  */
1612 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1613 {
1614   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1615     {
1616       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1617       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1618       return s1==s2?1:0;
1619     }
1620   return 0;
1621 }
1622
1623 /*!
1624  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1625  */
1626 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1627 {
1628   int sz=connI[cell1+1]-connI[cell1];
1629   if(sz==connI[cell2+1]-connI[cell2])
1630     {
1631       if(conn[connI[cell1]]==conn[connI[cell2]])
1632         {
1633           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1634           unsigned dim=cm.getDimension();
1635           if(dim!=3)
1636             {
1637               if(dim!=1)
1638                 {
1639                   int sz1=2*(sz-1);
1640                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1641                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1642                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1643                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1644                   if(work!=tmp+sz1)
1645                     return 1;
1646                   else
1647                     {
1648                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1649                       std::reverse_iterator<int *> it2((int *)tmp);
1650                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1651                         return 2;
1652                       else
1653                         return 0;
1654                     }
1655
1656                   return work!=tmp+sz1?1:0;
1657                 }
1658               else
1659                 {//case of SEG2 and SEG3
1660                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1661                     return 1;
1662                   if(!cm.isQuadratic())
1663                     {
1664                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1665                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1666                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1667                         return 2;
1668                       return 0;
1669                     }
1670                   else
1671                     {
1672                       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])
1673                         return 2;
1674                       return 0;
1675                     }
1676                 }
1677             }
1678           else
1679             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1680         }
1681     }
1682   return 0;
1683 }
1684
1685
1686 /*!
1687  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1688  * by \a compType.
1689  * This method keeps the coordiantes of \a this. This method is time consuming.
1690  *
1691  * \param [in] compType input specifying the technique used to compare cells each other.
1692  *   - 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.
1693  *   - 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)
1694  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1695  *   - 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
1696  * can be used for users not sensitive to orientation of cell
1697  * \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.
1698  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1699  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1700  * \return the correspondance array old to new in a newly allocated array.
1701  * 
1702  */
1703 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1704 {
1705   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1706   getReverseNodalConnectivity(revNodal,revNodalI);
1707   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1708 }
1709
1710 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1711                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1712 {
1713   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1714   int nbOfCells=nodalI->getNumberOfTuples()-1;
1715   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1716   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1717   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1718   std::vector<bool> isFetched(nbOfCells,false);
1719   if(startCellId==0)
1720     {
1721       for(int i=0;i<nbOfCells;i++)
1722         {
1723           if(!isFetched[i])
1724             {
1725               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1726               std::vector<int> v,v2;
1727               if(connOfNode!=connPtr+connIPtr[i+1])
1728                 {
1729                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1730                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1731                   connOfNode++;
1732                 }
1733               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1734                 if(*connOfNode>=0)
1735                   {
1736                     v=v2;
1737                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1738                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1739                     v2.resize(std::distance(v2.begin(),it));
1740                   }
1741               if(v2.size()>1)
1742                 {
1743                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1744                     {
1745                       int pos=commonCellsI->back();
1746                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1747                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1748                         isFetched[*it]=true;
1749                     }
1750                 }
1751             }
1752         }
1753     }
1754   else
1755     {
1756       for(int i=startCellId;i<nbOfCells;i++)
1757         {
1758           if(!isFetched[i])
1759             {
1760               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1761               std::vector<int> v,v2;
1762               if(connOfNode!=connPtr+connIPtr[i+1])
1763                 {
1764                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1765                   connOfNode++;
1766                 }
1767               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1768                 if(*connOfNode>=0)
1769                   {
1770                     v=v2;
1771                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1772                     v2.resize(std::distance(v2.begin(),it));
1773                   }
1774               if(v2.size()>1)
1775                 {
1776                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1777                     {
1778                       int pos=commonCellsI->back();
1779                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1780                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1781                         isFetched[*it]=true;
1782                     }
1783                 }
1784             }
1785         }
1786     }
1787   commonCellsArr=commonCells.retn();
1788   commonCellsIArr=commonCellsI.retn();
1789 }
1790
1791 /*!
1792  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1793  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1794  * than \a this->getNumberOfCells() in the returned array means that there is no
1795  * corresponding cell in \a this mesh.
1796  * It is expected that \a this and \a other meshes share the same node coordinates
1797  * array, if it is not so an exception is thrown. 
1798  *  \param [in] other - the mesh to compare with.
1799  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1800  *         valid values [0,1,2], see zipConnectivityTraducer().
1801  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1802  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1803  *         values. The caller is to delete this array using
1804  *         decrRef() as it is no more needed.
1805  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1806  *         mesh.
1807  *
1808  *  \if ENABLE_EXAMPLES
1809  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1810  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1811  *  \endif
1812  *  \sa checkDeepEquivalOnSameNodesWith()
1813  *  \sa checkGeoEquivalWith()
1814  */
1815 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1816 {
1817   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1818   int nbOfCells=getNumberOfCells();
1819   static const int possibleCompType[]={0,1,2};
1820   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1821     {
1822       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1823       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1824       oss << " !";
1825       throw INTERP_KERNEL::Exception(oss.str());
1826     }
1827   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1828   arr=o2n->subArray(nbOfCells);
1829   arr->setName(other->getName());
1830   int tmp;
1831   if(other->getNumberOfCells()==0)
1832     return true;
1833   return arr->getMaxValue(tmp)<nbOfCells;
1834 }
1835
1836 /*!
1837  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1838  * This method tries to determine if \b other is fully included in \b this.
1839  * The main difference is that this method is not expected to throw exception.
1840  * This method has two outputs :
1841  *
1842  * \param other other mesh
1843  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1844  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1845  */
1846 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1847 {
1848   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1849   DataArrayInt *commonCells=0,*commonCellsI=0;
1850   int thisNbCells=getNumberOfCells();
1851   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1852   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1853   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1854   int otherNbCells=other->getNumberOfCells();
1855   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1856   arr2->alloc(otherNbCells,1);
1857   arr2->fillWithZero();
1858   int *arr2Ptr=arr2->getPointer();
1859   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1860   for(int i=0;i<nbOfCommon;i++)
1861     {
1862       int start=commonCellsPtr[commonCellsIPtr[i]];
1863       if(start<thisNbCells)
1864         {
1865           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1866             {
1867               int sig=commonCellsPtr[j]>0?1:-1;
1868               int val=std::abs(commonCellsPtr[j])-1;
1869               if(val>=thisNbCells)
1870                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1871             }
1872         }
1873     }
1874   arr2->setName(other->getName());
1875   if(arr2->presenceOfValue(0))
1876     return false;
1877   arr=arr2.retn();
1878   return true;
1879 }
1880
1881 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1882 {
1883   if(!other)
1884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1885   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1886   if(!otherC)
1887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1888   std::vector<const MEDCouplingUMesh *> ms(2);
1889   ms[0]=this;
1890   ms[1]=otherC;
1891   return MergeUMeshesOnSameCoords(ms);
1892 }
1893
1894 /*!
1895  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1896  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1897  * cellIds is not given explicitely but by a range python like.
1898  * 
1899  * \param start
1900  * \param end
1901  * \param step
1902  * \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.
1903  * \return a newly allocated
1904  * 
1905  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1906  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1907  */
1908 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
1909 {
1910   if(getMeshDimension()!=-1)
1911     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
1912   else
1913     {
1914       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
1915       if(newNbOfCells!=1)
1916         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1917       if(start!=0)
1918         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1919       incrRef();
1920       return const_cast<MEDCouplingUMesh *>(this);
1921     }
1922 }
1923
1924 /*!
1925  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1926  * The result mesh shares or not the node coordinates array with \a this mesh depending
1927  * on \a keepCoords parameter.
1928  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1929  *           to write this mesh to the MED file, its cells must be sorted using
1930  *           sortCellsInMEDFileFrmt().
1931  *  \param [in] begin - an array of cell ids to include to the new mesh.
1932  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1933  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1934  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1935  *         by calling zipCoords().
1936  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
1937  *         to delete this mesh using decrRef() as it is no more needed. 
1938  *  \throw If the coordinates array is not set.
1939  *  \throw If the nodal connectivity of cells is not defined.
1940  *  \throw If any cell id in the array \a begin is not valid.
1941  *
1942  *  \if ENABLE_EXAMPLES
1943  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1944  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1945  *  \endif
1946  */
1947 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1948 {
1949   if(getMeshDimension()!=-1)
1950     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
1951   else
1952     {
1953       if(end-begin!=1)
1954         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1955       if(begin[0]!=0)
1956         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1957       incrRef();
1958       return const_cast<MEDCouplingUMesh *>(this);
1959     }
1960 }
1961
1962 /*!
1963  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1964  *
1965  * 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.
1966  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1967  * The number of cells of \b this will remain the same with this method.
1968  *
1969  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
1970  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
1971  * \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 ).
1972  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1973  */
1974 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1975 {
1976   checkConnectivityFullyDefined();
1977   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1978   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1979     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1980   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1981     {
1982       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1983       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1984       throw INTERP_KERNEL::Exception(oss.str());
1985     }
1986   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1987   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1988     {
1989       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1990       throw INTERP_KERNEL::Exception(oss.str());
1991     }
1992   int nbOfCells=getNumberOfCells();
1993   bool easyAssign=true;
1994   const int *connI=_nodal_connec_index->getConstPointer();
1995   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1996   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1997     {
1998       if(*it>=0 && *it<nbOfCells)
1999         {
2000           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2001         }
2002       else
2003         {
2004           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2005           throw INTERP_KERNEL::Exception(oss.str());
2006         }
2007     }
2008   if(easyAssign)
2009     {
2010       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2011       computeTypes();
2012     }
2013   else
2014     {
2015       DataArrayInt *arrOut=0,*arrIOut=0;
2016       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2017                                                arrOut,arrIOut);
2018       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2019       setConnectivity(arrOut,arrIOut,true);
2020     }
2021 }
2022
2023 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2024 {
2025   checkConnectivityFullyDefined();
2026   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2027   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2029   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2030     {
2031       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2032       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2033       throw INTERP_KERNEL::Exception(oss.str());
2034     }
2035   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2036   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2037     {
2038       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2039       throw INTERP_KERNEL::Exception(oss.str());
2040     }
2041   int nbOfCells=getNumberOfCells();
2042   bool easyAssign=true;
2043   const int *connI=_nodal_connec_index->getConstPointer();
2044   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2045   int it=start;
2046   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2047     {
2048       if(it>=0 && it<nbOfCells)
2049         {
2050           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2051         }
2052       else
2053         {
2054           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2055           throw INTERP_KERNEL::Exception(oss.str());
2056         }
2057     }
2058   if(easyAssign)
2059     {
2060       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2061       computeTypes();
2062     }
2063   else
2064     {
2065       DataArrayInt *arrOut=0,*arrIOut=0;
2066       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2067                                                 arrOut,arrIOut);
2068       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2069       setConnectivity(arrOut,arrIOut,true);
2070     }
2071 }                      
2072
2073
2074 /*!
2075  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2076  * this->getMeshDimension(), that bound some cells of \a this mesh.
2077  * The cells of lower dimension to include to the result mesh are selected basing on
2078  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2079  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2080  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2081  * created mesh shares the node coordinates array with \a this mesh. 
2082  *  \param [in] begin - the array of node ids.
2083  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2084  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2085  *         array \a begin are added, else cells whose any node is in the
2086  *         array \a begin are added.
2087  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2088  *         to delete this mesh using decrRef() as it is no more needed. 
2089  *  \throw If the coordinates array is not set.
2090  *  \throw If the nodal connectivity of cells is not defined.
2091  *  \throw If any node id in \a begin is not valid.
2092  *
2093  *  \if ENABLE_EXAMPLES
2094  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2095  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2096  *  \endif
2097  */
2098 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2099 {
2100   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2101   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2102   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2103   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2104   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2105 }
2106
2107 /*!
2108  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2109  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2110  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2111  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2112  *         by calling zipCoords().
2113  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2114  *         to delete this mesh using decrRef() as it is no more needed. 
2115  *  \throw If the coordinates array is not set.
2116  *  \throw If the nodal connectivity of cells is not defined.
2117  *
2118  *  \if ENABLE_EXAMPLES
2119  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2120  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2121  *  \endif
2122  */
2123 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2124 {
2125   DataArrayInt *desc=DataArrayInt::New();
2126   DataArrayInt *descIndx=DataArrayInt::New();
2127   DataArrayInt *revDesc=DataArrayInt::New();
2128   DataArrayInt *revDescIndx=DataArrayInt::New();
2129   //
2130   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2131   revDesc->decrRef();
2132   desc->decrRef();
2133   descIndx->decrRef();
2134   int nbOfCells=meshDM1->getNumberOfCells();
2135   const int *revDescIndxC=revDescIndx->getConstPointer();
2136   std::vector<int> boundaryCells;
2137   for(int i=0;i<nbOfCells;i++)
2138     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2139       boundaryCells.push_back(i);
2140   revDescIndx->decrRef();
2141   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2142   return ret;
2143 }
2144
2145 /*!
2146  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2147  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2148  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2149  */
2150 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2151 {
2152   checkFullyDefined();
2153   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2154   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2155   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2156   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2157   //
2158   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2159   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2160   //
2161   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2162   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2163   const int *revDescPtr=revDesc->getConstPointer();
2164   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2165   int nbOfCells=getNumberOfCells();
2166   std::vector<bool> ret1(nbOfCells,false);
2167   int sz=0;
2168   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2169     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2170       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2171   //
2172   DataArrayInt *ret2=DataArrayInt::New();
2173   ret2->alloc(sz,1);
2174   int *ret2Ptr=ret2->getPointer();
2175   sz=0;
2176   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2177     if(*it)
2178       *ret2Ptr++=sz;
2179   ret2->setName("BoundaryCells");
2180   return ret2;
2181 }
2182
2183 /*!
2184  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2185  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2186  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2187  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2188  *
2189  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2190  * 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
2191  * equals a cell in \b otherDimM1OnSameCoords.
2192  *
2193  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2194  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2195  *
2196  * \param [in] otherDimM1OnSameCoords
2197  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2198  * \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
2199  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2200  */
2201 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2202 {
2203   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2204     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2205   checkConnectivityFullyDefined();
2206   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2207   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2208     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2209   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2210   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2211   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2212   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2213   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2214   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2215   DataArrayInt *idsOtherInConsti=0;
2216   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2217   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2218   if(!b)
2219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2220   std::set<int> s1;
2221   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2222     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2223   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2224   s1arr_renum1->sort();
2225   cellIdsRk0=s0arr.retn();
2226   //cellIdsRk1=s_renum1.retn();
2227   cellIdsRk1=s1arr_renum1.retn();
2228 }
2229
2230 /*!
2231  * 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
2232  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2233  * 
2234  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2235  */
2236 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2237 {
2238   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2239   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2240   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2241   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2242   //
2243   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2244   revDesc=0; desc=0; descIndx=0;
2245   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2246   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2247   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2248 }
2249
2250 /*!
2251  * Finds nodes lying on the boundary of \a this mesh.
2252  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2253  *          nodes. The caller is to delete this array using decrRef() as it is no
2254  *          more needed.
2255  *  \throw If the coordinates array is not set.
2256  *  \throw If the nodal connectivity of cells is node defined.
2257  *
2258  *  \if ENABLE_EXAMPLES
2259  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2260  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2261  *  \endif
2262  */
2263 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2264 {
2265   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2266   return skin->computeFetchedNodeIds();
2267 }
2268
2269 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2270 {
2271   incrRef();
2272   return const_cast<MEDCouplingUMesh *>(this);
2273 }
2274
2275 /*!
2276  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2277  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2278  * 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.
2279  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2280  * 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.
2281  *
2282  * \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
2283  *             parameter is altered during the call.
2284  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2285  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2286  * \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.
2287  *
2288  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2289  */
2290 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2291                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2292 {
2293   typedef MCAuto<DataArrayInt> DAInt;
2294   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2295
2296   checkFullyDefined();
2297   otherDimM1OnSameCoords.checkFullyDefined();
2298   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2299     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2300   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2302
2303   // Checking star-shaped M1 group:
2304   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2305   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2306   DAInt dsi = rdit0->deltaShiftIndex();
2307   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2308   if(idsTmp0->getNumberOfTuples())
2309     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2310   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2311
2312   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2313   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2314   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2315   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2316   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2317   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2318   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2319   dsi = rdit0->deltaShiftIndex();
2320   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2321   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2322   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2323   // In 3D, some points on the boundary of M0 still need duplication:
2324   DAInt notDup = 0;
2325   if (getMeshDimension() == 3)
2326     {
2327       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2328       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2329       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2330       DataArrayInt * corresp=0;
2331       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2332       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2333       corresp->decrRef();
2334       if (validIds->getNumberOfTuples())
2335         {
2336           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2337           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2338           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2339           notDup = xtrem->buildSubstraction(fNodes1);
2340         }
2341       else
2342         notDup = xtrem->buildSubstraction(fNodes);
2343     }
2344   else
2345     notDup = xtrem->buildSubstraction(fNodes);
2346
2347   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2348   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2349   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2350   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2351
2352   //
2353   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2354   int nCells2 = m0Part2->getNumberOfCells();
2355   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2356   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2357
2358   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2359   DataArrayInt *tmp00=0,*tmp11=0;
2360   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2361   DAInt neighInit00(tmp00);
2362   DAInt neighIInit00(tmp11);
2363   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2364   DataArrayInt *idsTmp=0;
2365   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2366   DAInt ids(idsTmp);
2367   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2368   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2369   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2370   DataArrayInt *tmp0=0,*tmp1=0;
2371   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2372   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2373   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2374   DAInt neigh00(tmp0);
2375   DAInt neighI00(tmp1);
2376
2377   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2378   int seed = 0, nIter = 0;
2379   int nIterMax = nCells2+1; // Safety net for the loop
2380   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2381   hitCells->fillWithValue(-1);
2382   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2383   cellsToModifyConn0_torenum->alloc(0,1);
2384   while (nIter < nIterMax)
2385     {
2386       DAInt t = hitCells->findIdsEqual(-1);
2387       if (!t->getNumberOfTuples())
2388         break;
2389       // Connex zone without the crack (to compute the next seed really)
2390       int dnu;
2391       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2392       int cnt = 0;
2393       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2394         hitCells->setIJ(*ptr,0,1);
2395       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2396       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2397       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2398       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2399       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2400       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2401       DAInt intersec = nonHitCells->buildIntersection(comple);
2402       if (intersec->getNumberOfTuples())
2403         { seed = intersec->getIJ(0,0); }
2404       else
2405         { break; }
2406       nIter++;
2407     }
2408   if (nIter >= nIterMax)
2409     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2410
2411   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2412   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2413   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2414   //
2415   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2416   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2417   nodeIdsToDuplicate=dupl.retn();
2418 }
2419
2420 /*!
2421  * This method operates a modification of the connectivity and coords in \b this.
2422  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2423  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2424  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2425  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2426  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2427  * 
2428  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2429  * 
2430  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2431  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2432  */
2433 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2434 {
2435   int nbOfNodes=getNumberOfNodes();
2436   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2437   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2438 }
2439
2440 /*!
2441  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2442  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2443  *
2444  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2445  *
2446  * \sa renumberNodesInConn
2447  */
2448 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2449 {
2450   checkConnectivityFullyDefined();
2451   int *conn(getNodalConnectivity()->getPointer());
2452   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2453   int nbOfCells(getNumberOfCells());
2454   for(int i=0;i<nbOfCells;i++)
2455     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2456       {
2457         int& node=conn[iconn];
2458         if(node>=0)//avoid polyhedron separator
2459           {
2460             node+=offset;
2461           }
2462       }
2463   _nodal_connec->declareAsNew();
2464   updateTime();
2465 }
2466
2467 /*!
2468  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2469  *  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
2470  *  of a big mesh.
2471  */
2472 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2473 {
2474   checkConnectivityFullyDefined();
2475   int *conn(getNodalConnectivity()->getPointer());
2476   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2477   int nbOfCells(getNumberOfCells());
2478   for(int i=0;i<nbOfCells;i++)
2479     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2480       {
2481         int& node=conn[iconn];
2482         if(node>=0)//avoid polyhedron separator
2483           {
2484             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2485             if(it!=newNodeNumbersO2N.end())
2486               {
2487                 node=(*it).second;
2488               }
2489             else
2490               {
2491                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2492                 throw INTERP_KERNEL::Exception(oss.str());
2493               }
2494           }
2495       }
2496   _nodal_connec->declareAsNew();
2497   updateTime();
2498 }
2499
2500 /*!
2501  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2502  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2503  * This method is a generalization of shiftNodeNumbersInConn().
2504  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2505  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2506  *         this->getNumberOfNodes(), in "Old to New" mode. 
2507  *         See \ref numbering for more info on renumbering modes.
2508  *  \throw If the nodal connectivity of cells is not defined.
2509  *
2510  *  \if ENABLE_EXAMPLES
2511  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2512  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2513  *  \endif
2514  */
2515 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2516 {
2517   checkConnectivityFullyDefined();
2518   int *conn=getNodalConnectivity()->getPointer();
2519   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2520   int nbOfCells(getNumberOfCells());
2521   for(int i=0;i<nbOfCells;i++)
2522     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2523       {
2524         int& node=conn[iconn];
2525         if(node>=0)//avoid polyhedron separator
2526           {
2527             node=newNodeNumbersO2N[node];
2528           }
2529       }
2530   _nodal_connec->declareAsNew();
2531   updateTime();
2532 }
2533
2534 /*!
2535  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2536  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2537  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2538  * 
2539  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2540  */
2541 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2542 {
2543   checkConnectivityFullyDefined();
2544   int *conn=getNodalConnectivity()->getPointer();
2545   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2546   int nbOfCells=getNumberOfCells();
2547   for(int i=0;i<nbOfCells;i++)
2548     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2549       {
2550         int& node=conn[iconn];
2551         if(node>=0)//avoid polyhedron separator
2552           {
2553             node+=delta;
2554           }
2555       }
2556   _nodal_connec->declareAsNew();
2557   updateTime();
2558 }
2559
2560 /*!
2561  * This method operates a modification of the connectivity in \b this.
2562  * 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.
2563  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2564  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2565  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2566  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2567  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2568  * 
2569  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2570  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2571  * 
2572  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2573  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2574  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2575  */
2576 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2577 {
2578   checkConnectivityFullyDefined();
2579   std::map<int,int> m;
2580   int val=offset;
2581   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2582     m[*work]=val;
2583   int *conn=getNodalConnectivity()->getPointer();
2584   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2585   int nbOfCells=getNumberOfCells();
2586   for(int i=0;i<nbOfCells;i++)
2587     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2588       {
2589         int& node=conn[iconn];
2590         if(node>=0)//avoid polyhedron separator
2591           {
2592             std::map<int,int>::iterator it=m.find(node);
2593             if(it!=m.end())
2594               node=(*it).second;
2595           }
2596       }
2597   updateTime();
2598 }
2599
2600 /*!
2601  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2602  *
2603  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2604  * After the call of this method the number of cells remains the same as before.
2605  *
2606  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2607  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2608  * be strictly in [0;this->getNumberOfCells()).
2609  *
2610  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2611  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2612  * should be contained in[0;this->getNumberOfCells()).
2613  * 
2614  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2615  * \param check
2616  */
2617 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2618 {
2619   checkConnectivityFullyDefined();
2620   int nbCells=getNumberOfCells();
2621   const int *array=old2NewBg;
2622   if(check)
2623     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2624   //
2625   const int *conn=_nodal_connec->getConstPointer();
2626   const int *connI=_nodal_connec_index->getConstPointer();
2627   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2628   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2629   const int *n2oPtr=n2o->begin();
2630   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2631   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2632   newConn->copyStringInfoFrom(*_nodal_connec);
2633   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2634   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2635   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2636   //
2637   int *newC=newConn->getPointer();
2638   int *newCI=newConnI->getPointer();
2639   int loc=0;
2640   newCI[0]=loc;
2641   for(int i=0;i<nbCells;i++)
2642     {
2643       int pos=n2oPtr[i];
2644       int nbOfElts=connI[pos+1]-connI[pos];
2645       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2646       loc+=nbOfElts;
2647       newCI[i+1]=loc;
2648     }
2649   //
2650   setConnectivity(newConn,newConnI);
2651   if(check)
2652     free(const_cast<int *>(array));
2653 }
2654
2655 /*!
2656  * Finds cells whose bounding boxes intersect a given bounding box.
2657  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2658  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2659  *         zMax (if in 3D). 
2660  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2661  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2662  *         extent of the bounding box of cell to produce an addition to this bounding box.
2663  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2664  *         cells. The caller is to delete this array using decrRef() as it is no more
2665  *         needed. 
2666  *  \throw If the coordinates array is not set.
2667  *  \throw If the nodal connectivity of cells is not defined.
2668  *
2669  *  \if ENABLE_EXAMPLES
2670  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2671  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2672  *  \endif
2673  */
2674 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2675 {
2676   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2677   if(getMeshDimension()==-1)
2678     {
2679       elems->pushBackSilent(0);
2680       return elems.retn();
2681     }
2682   int dim=getSpaceDimension();
2683   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2684   const int* conn      = getNodalConnectivity()->getConstPointer();
2685   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2686   const double* coords = getCoords()->getConstPointer();
2687   int nbOfCells=getNumberOfCells();
2688   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2689     {
2690       for (int i=0; i<dim; i++)
2691         {
2692           elem_bb[i*2]=std::numeric_limits<double>::max();
2693           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2694         }
2695
2696       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2697         {
2698           int node= conn[inode];
2699           if(node>=0)//avoid polyhedron separator
2700             {
2701               for (int idim=0; idim<dim; idim++)
2702                 {
2703                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2704                     {
2705                       elem_bb[idim*2] = coords[node*dim+idim] ;
2706                     }
2707                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2708                     {
2709                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2710                     }
2711                 }
2712             }
2713         }
2714       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2715         elems->pushBackSilent(ielem);
2716     }
2717   return elems.retn();
2718 }
2719
2720 /*!
2721  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2722  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2723  * added in 'elems' parameter.
2724  */
2725 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2726 {
2727   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2728   if(getMeshDimension()==-1)
2729     {
2730       elems->pushBackSilent(0);
2731       return elems.retn();
2732     }
2733   int dim=getSpaceDimension();
2734   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2735   const int* conn      = getNodalConnectivity()->getConstPointer();
2736   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2737   const double* coords = getCoords()->getConstPointer();
2738   int nbOfCells=getNumberOfCells();
2739   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2740     {
2741       for (int i=0; i<dim; i++)
2742         {
2743           elem_bb[i*2]=std::numeric_limits<double>::max();
2744           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2745         }
2746
2747       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2748         {
2749           int node= conn[inode];
2750           if(node>=0)//avoid polyhedron separator
2751             {
2752               for (int idim=0; idim<dim; idim++)
2753                 {
2754                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2755                     {
2756                       elem_bb[idim*2] = coords[node*dim+idim] ;
2757                     }
2758                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2759                     {
2760                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2761                     }
2762                 }
2763             }
2764         }
2765       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2766         elems->pushBackSilent(ielem);
2767     }
2768   return elems.retn();
2769 }
2770
2771 /*!
2772  * Returns a type of a cell by its id.
2773  *  \param [in] cellId - the id of the cell of interest.
2774  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2775  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2776  */
2777 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2778 {
2779   const int *ptI=_nodal_connec_index->getConstPointer();
2780   const int *pt=_nodal_connec->getConstPointer();
2781   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2782     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2783   else
2784     {
2785       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2786       throw INTERP_KERNEL::Exception(oss.str());
2787     }
2788 }
2789
2790 /*!
2791  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2792  * This method does not throw exception if geometric type \a type is not in \a this.
2793  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2794  * The coordinates array is not considered here.
2795  *
2796  * \param [in] type the geometric type
2797  * \return cell ids in this having geometric type \a type.
2798  */
2799 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2800 {
2801
2802   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2803   ret->alloc(0,1);
2804   checkConnectivityFullyDefined();
2805   int nbCells=getNumberOfCells();
2806   int mdim=getMeshDimension();
2807   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2808   if(mdim!=(int)cm.getDimension())
2809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2810   const int *ptI=_nodal_connec_index->getConstPointer();
2811   const int *pt=_nodal_connec->getConstPointer();
2812   for(int i=0;i<nbCells;i++)
2813     {
2814       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2815         ret->pushBackSilent(i);
2816     }
2817   return ret.retn();
2818 }
2819
2820 /*!
2821  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2822  */
2823 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2824 {
2825   const int *ptI=_nodal_connec_index->getConstPointer();
2826   const int *pt=_nodal_connec->getConstPointer();
2827   int nbOfCells=getNumberOfCells();
2828   int ret=0;
2829   for(int i=0;i<nbOfCells;i++)
2830     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2831       ret++;
2832   return ret;
2833 }
2834
2835 /*!
2836  * Returns the nodal connectivity of a given cell.
2837  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2838  * all returned node ids can be used in getCoordinatesOfNode().
2839  *  \param [in] cellId - an id of the cell of interest.
2840  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2841  *         cleared before the appending.
2842  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2843  */
2844 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2845 {
2846   const int *ptI=_nodal_connec_index->getConstPointer();
2847   const int *pt=_nodal_connec->getConstPointer();
2848   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2849     if(*w>=0)
2850       conn.push_back(*w);
2851 }
2852
2853 std::string MEDCouplingUMesh::simpleRepr() const
2854 {
2855   static const char msg0[]="No coordinates specified !";
2856   std::ostringstream ret;
2857   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2858   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2859   int tmpp1,tmpp2;
2860   double tt=getTime(tmpp1,tmpp2);
2861   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2862   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2863   if(_mesh_dim>=-1)
2864     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2865   else
2866     { ret << " Mesh dimension has not been set or is invalid !"; }
2867   if(_coords!=0)
2868     {
2869       const int spaceDim=getSpaceDimension();
2870       ret << spaceDim << "\nInfo attached on space dimension : ";
2871       for(int i=0;i<spaceDim;i++)
2872         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2873       ret << "\n";
2874     }
2875   else
2876     ret << msg0 << "\n";
2877   ret << "Number of nodes : ";
2878   if(_coords!=0)
2879     ret << getNumberOfNodes() << "\n";
2880   else
2881     ret << msg0 << "\n";
2882   ret << "Number of cells : ";
2883   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2884     ret << getNumberOfCells() << "\n";
2885   else
2886     ret << "No connectivity specified !" << "\n";
2887   ret << "Cell types present : ";
2888   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2889     {
2890       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2891       ret << cm.getRepr() << " ";
2892     }
2893   ret << "\n";
2894   return ret.str();
2895 }
2896
2897 std::string MEDCouplingUMesh::advancedRepr() const
2898 {
2899   std::ostringstream ret;
2900   ret << simpleRepr();
2901   ret << "\nCoordinates array : \n___________________\n\n";
2902   if(_coords)
2903     _coords->reprWithoutNameStream(ret);
2904   else
2905     ret << "No array set !\n";
2906   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2907   reprConnectivityOfThisLL(ret);
2908   return ret.str();
2909 }
2910
2911 /*!
2912  * This method returns a C++ code that is a dump of \a this.
2913  * This method will throw if this is not fully defined.
2914  */
2915 std::string MEDCouplingUMesh::cppRepr() const
2916 {
2917   static const char coordsName[]="coords";
2918   static const char connName[]="conn";
2919   static const char connIName[]="connI";
2920   checkFullyDefined();
2921   std::ostringstream ret; ret << "// coordinates" << std::endl;
2922   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2923   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2924   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2925   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2926   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2927   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2928   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2929   return ret.str();
2930 }
2931
2932 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2933 {
2934   std::ostringstream ret;
2935   reprConnectivityOfThisLL(ret);
2936   return ret.str();
2937 }
2938
2939 /*!
2940  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2941  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2942  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2943  * some algos).
2944  * 
2945  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2946  * 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
2947  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2948  */
2949 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2950 {
2951   int mdim=getMeshDimension();
2952   if(mdim<0)
2953     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2954   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2955   MCAuto<DataArrayInt> tmp1,tmp2;
2956   bool needToCpyCT=true;
2957   if(!_nodal_connec)
2958     {
2959       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2960       needToCpyCT=false;
2961     }
2962   else
2963     {
2964       tmp1=_nodal_connec;
2965       tmp1->incrRef();
2966     }
2967   if(!_nodal_connec_index)
2968     {
2969       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2970       needToCpyCT=false;
2971     }
2972   else
2973     {
2974       tmp2=_nodal_connec_index;
2975       tmp2->incrRef();
2976     }
2977   ret->setConnectivity(tmp1,tmp2,false);
2978   if(needToCpyCT)
2979     ret->_types=_types;
2980   if(!_coords)
2981     {
2982       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2983       ret->setCoords(coords);
2984     }
2985   else
2986     ret->setCoords(_coords);
2987   return ret.retn();
2988 }
2989
2990 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2991 {
2992   const int *ptI=_nodal_connec_index->getConstPointer();
2993   const int *pt=_nodal_connec->getConstPointer();
2994   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2995     return ptI[cellId+1]-ptI[cellId]-1;
2996   else
2997     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2998 }
2999
3000 /*!
3001  * Returns types of cells of the specified part of \a this mesh.
3002  * This method avoids computing sub-mesh explicitely to get its types.
3003  *  \param [in] begin - an array of cell ids of interest.
3004  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3005  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3006  *         describing the cell types. 
3007  *  \throw If the coordinates array is not set.
3008  *  \throw If the nodal connectivity of cells is not defined.
3009  *  \sa getAllGeoTypes()
3010  */
3011 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3012 {
3013   checkFullyDefined();
3014   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3015   const int *conn=_nodal_connec->getConstPointer();
3016   const int *connIndex=_nodal_connec_index->getConstPointer();
3017   for(const int *w=begin;w!=end;w++)
3018     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3019   return ret;
3020 }
3021
3022 /*!
3023  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3024  * Optionally updates
3025  * a set of types of cells constituting \a this mesh. 
3026  * This method is for advanced users having prepared their connectivity before. For
3027  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3028  *  \param [in] conn - the nodal connectivity array. 
3029  *  \param [in] connIndex - the nodal connectivity index array.
3030  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3031  *         mesh is updated.
3032  */
3033 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3034 {
3035   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3036   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3037   if(isComputingTypes)
3038     computeTypes();
3039   declareAsNew();
3040 }
3041
3042 /*!
3043  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3044  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3045  */
3046 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3047     _nodal_connec(0),_nodal_connec_index(0),
3048     _types(other._types)
3049 {
3050   if(other._nodal_connec)
3051     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3052   if(other._nodal_connec_index)
3053     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3054 }
3055
3056 MEDCouplingUMesh::~MEDCouplingUMesh()
3057 {
3058   if(_nodal_connec)
3059     _nodal_connec->decrRef();
3060   if(_nodal_connec_index)
3061     _nodal_connec_index->decrRef();
3062 }
3063
3064 /*!
3065  * Recomputes a set of cell types of \a this mesh. For more info see
3066  * \ref MEDCouplingUMeshNodalConnectivity.
3067  */
3068 void MEDCouplingUMesh::computeTypes()
3069 {
3070   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3071 }
3072
3073
3074 /*!
3075  * Returns a number of cells constituting \a this mesh. 
3076  *  \return int - the number of cells in \a this mesh.
3077  *  \throw If the nodal connectivity of cells is not defined.
3078  */
3079 int MEDCouplingUMesh::getNumberOfCells() const
3080
3081   if(_nodal_connec_index)
3082     return _nodal_connec_index->getNumberOfTuples()-1;
3083   else
3084     if(_mesh_dim==-1)
3085       return 1;
3086     else
3087       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3088 }
3089
3090 /*!
3091  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3092  * mesh. For more info see \ref meshes.
3093  *  \return int - the dimension of \a this mesh.
3094  *  \throw If the mesh dimension is not defined using setMeshDimension().
3095  */
3096 int MEDCouplingUMesh::getMeshDimension() const
3097 {
3098   if(_mesh_dim<-1)
3099     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3100   return _mesh_dim;
3101 }
3102
3103 /*!
3104  * Returns a length of the nodal connectivity array.
3105  * This method is for test reason. Normally the integer returned is not useable by
3106  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3107  *  \return int - the length of the nodal connectivity array.
3108  */
3109 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3110 {
3111   return _nodal_connec->getNbOfElems();
3112 }
3113
3114 /*!
3115  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3116  */
3117 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3118 {
3119   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3120   tinyInfo.push_back(getMeshDimension());
3121   tinyInfo.push_back(getNumberOfCells());
3122   if(_nodal_connec)
3123     tinyInfo.push_back(getNodalConnectivityArrayLen());
3124   else
3125     tinyInfo.push_back(-1);
3126 }
3127
3128 /*!
3129  * First step of unserialization process.
3130  */
3131 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3132 {
3133   return tinyInfo[6]<=0;
3134 }
3135
3136 /*!
3137  * Second step of serialization process.
3138  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3139  * \param a1
3140  * \param a2
3141  * \param littleStrings
3142  */
3143 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3144 {
3145   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3146   if(tinyInfo[5]!=-1)
3147     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3148 }
3149
3150 /*!
3151  * Third and final step of serialization process.
3152  */
3153 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3154 {
3155   MEDCouplingPointSet::serialize(a1,a2);
3156   if(getMeshDimension()>-1)
3157     {
3158       a1=DataArrayInt::New();
3159       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3160       int *ptA1=a1->getPointer();
3161       const int *conn=getNodalConnectivity()->getConstPointer();
3162       const int *index=getNodalConnectivityIndex()->getConstPointer();
3163       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3164       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3165     }
3166   else
3167     a1=0;
3168 }
3169
3170 /*!
3171  * Second and final unserialization process.
3172  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3173  */
3174 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3175 {
3176   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3177   setMeshDimension(tinyInfo[5]);
3178   if(tinyInfo[7]!=-1)
3179     {
3180       // Connectivity
3181       const int *recvBuffer=a1->getConstPointer();
3182       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3183       myConnecIndex->alloc(tinyInfo[6]+1,1);
3184       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3185       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3186       myConnec->alloc(tinyInfo[7],1);
3187       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3188       setConnectivity(myConnec, myConnecIndex);
3189     }
3190 }
3191
3192
3193
3194 /*!
3195  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3196  * mesh.<br>
3197  * For 1D cells, the returned field contains lengths.<br>
3198  * For 2D cells, the returned field contains areas.<br>
3199  * For 3D cells, the returned field contains volumes.
3200  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3201  *         orientation, i.e. the volume is always positive.
3202  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3203  *         and one time . The caller is to delete this field using decrRef() as it is no
3204  *         more needed.
3205  */
3206 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3207 {
3208   std::string name="MeasureOfMesh_";
3209   name+=getName();
3210   int nbelem=getNumberOfCells();
3211   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3212   field->setName(name);
3213   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3214   array->alloc(nbelem,1);
3215   double *area_vol=array->getPointer();
3216   field->setArray(array) ; array=0;
3217   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3218   field->synchronizeTimeWithMesh();
3219   if(getMeshDimension()!=-1)
3220     {
3221       int ipt;
3222       INTERP_KERNEL::NormalizedCellType type;
3223       int dim_space=getSpaceDimension();
3224       const double *coords=getCoords()->getConstPointer();
3225       const int *connec=getNodalConnectivity()->getConstPointer();
3226       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3227       for(int iel=0;iel<nbelem;iel++)
3228         {
3229           ipt=connec_index[iel];
3230           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3231           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);
3232         }
3233       if(isAbs)
3234         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3235     }
3236   else
3237     {
3238       area_vol[0]=std::numeric_limits<double>::max();
3239     }
3240   return field.retn();
3241 }
3242
3243 /*!
3244  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3245  * mesh.<br>
3246  * For 1D cells, the returned array contains lengths.<br>
3247  * For 2D cells, the returned array contains areas.<br>
3248  * For 3D cells, the returned array contains volumes.
3249  * This method avoids building explicitly a part of \a this mesh to perform the work.
3250  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3251  *         orientation, i.e. the volume is always positive.
3252  *  \param [in] begin - an array of cell ids of interest.
3253  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3254  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3255  *          delete this array using decrRef() as it is no more needed.
3256  * 
3257  *  \if ENABLE_EXAMPLES
3258  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3259  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3260  *  \endif
3261  *  \sa getMeasureField()
3262  */
3263 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3264 {
3265   std::string name="PartMeasureOfMesh_";
3266   name+=getName();
3267   int nbelem=(int)std::distance(begin,end);
3268   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3269   array->setName(name);
3270   array->alloc(nbelem,1);
3271   double *area_vol=array->getPointer();
3272   if(getMeshDimension()!=-1)
3273     {
3274       int ipt;
3275       INTERP_KERNEL::NormalizedCellType type;
3276       int dim_space=getSpaceDimension();
3277       const double *coords=getCoords()->getConstPointer();
3278       const int *connec=getNodalConnectivity()->getConstPointer();
3279       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3280       for(const int *iel=begin;iel!=end;iel++)
3281         {
3282           ipt=connec_index[*iel];
3283           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3284           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3285         }
3286       if(isAbs)
3287         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3288     }
3289   else
3290     {
3291       area_vol[0]=std::numeric_limits<double>::max();
3292     }
3293   return array.retn();
3294 }
3295
3296 /*!
3297  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3298  * \a this one. The returned field contains the dual cell volume for each corresponding
3299  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3300  *  the dual mesh in P1 sens of \a this.<br>
3301  * For 1D cells, the returned field contains lengths.<br>
3302  * For 2D cells, the returned field contains areas.<br>
3303  * For 3D cells, the returned field contains volumes.
3304  * This method is useful to check "P1*" conservative interpolators.
3305  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3306  *         orientation, i.e. the volume is always positive.
3307  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3308  *          nodes and one time. The caller is to delete this array using decrRef() as
3309  *          it is no more needed.
3310  */
3311 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3312 {
3313   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3314   std::string name="MeasureOnNodeOfMesh_";
3315   name+=getName();
3316   int nbNodes=getNumberOfNodes();
3317   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3318   double cst=1./((double)getMeshDimension()+1.);
3319   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3320   array->alloc(nbNodes,1);
3321   double *valsToFill=array->getPointer();
3322   std::fill(valsToFill,valsToFill+nbNodes,0.);
3323   const double *values=tmp->getArray()->getConstPointer();
3324   MCAuto<DataArrayInt> da=DataArrayInt::New();
3325   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3326   getReverseNodalConnectivity(da,daInd);
3327   const int *daPtr=da->getConstPointer();
3328   const int *daIPtr=daInd->getConstPointer();
3329   for(int i=0;i<nbNodes;i++)
3330     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3331       valsToFill[i]+=cst*values[*cell];
3332   ret->setMesh(this);
3333   ret->setArray(array);
3334   return ret.retn();
3335 }
3336
3337 /*!
3338  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3339  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3340  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3341  * and are normalized.
3342  * <br> \a this can be either 
3343  * - a  2D mesh in 2D or 3D space or 
3344  * - an 1D mesh in 2D space.
3345  * 
3346  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3347  *          cells and one time. The caller is to delete this field using decrRef() as
3348  *          it is no more needed.
3349  *  \throw If the nodal connectivity of cells is not defined.
3350  *  \throw If the coordinates array is not set.
3351  *  \throw If the mesh dimension is not set.
3352  *  \throw If the mesh and space dimension is not as specified above.
3353  */
3354 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3355 {
3356   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3357     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3358   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3359   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3360   int nbOfCells=getNumberOfCells();
3361   int nbComp=getMeshDimension()+1;
3362   array->alloc(nbOfCells,nbComp);
3363   double *vals=array->getPointer();
3364   const int *connI=_nodal_connec_index->getConstPointer();
3365   const int *conn=_nodal_connec->getConstPointer();
3366   const double *coords=_coords->getConstPointer();
3367   if(getMeshDimension()==2)
3368     {
3369       if(getSpaceDimension()==3)
3370         {
3371           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3372           const double *locPtr=loc->getConstPointer();
3373           for(int i=0;i<nbOfCells;i++,vals+=3)
3374             {
3375               int offset=connI[i];
3376               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3377               double n=INTERP_KERNEL::norm<3>(vals);
3378               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3379             }
3380         }
3381       else
3382         {
3383           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3384           const double *isAbsPtr=isAbs->getArray()->begin();
3385           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3386             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3387         }
3388     }
3389   else//meshdimension==1
3390     {
3391       double tmp[2];
3392       for(int i=0;i<nbOfCells;i++)
3393         {
3394           int offset=connI[i];
3395           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3396           double n=INTERP_KERNEL::norm<2>(tmp);
3397           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3398           *vals++=-tmp[1];
3399           *vals++=tmp[0];
3400         }
3401     }
3402   ret->setArray(array);
3403   ret->setMesh(this);
3404   ret->synchronizeTimeWithSupport();
3405   return ret.retn();
3406 }
3407
3408 /*!
3409  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3410  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3411  * and are normalized.
3412  * <br> \a this can be either 
3413  * - a  2D mesh in 2D or 3D space or 
3414  * - an 1D mesh in 2D space.
3415  * 
3416  * This method avoids building explicitly a part of \a this mesh to perform the work.
3417  *  \param [in] begin - an array of cell ids of interest.
3418  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3419  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3420  *          cells and one time. The caller is to delete this field using decrRef() as
3421  *          it is no more needed.
3422  *  \throw If the nodal connectivity of cells is not defined.
3423  *  \throw If the coordinates array is not set.
3424  *  \throw If the mesh dimension is not set.
3425  *  \throw If the mesh and space dimension is not as specified above.
3426  *  \sa buildOrthogonalField()
3427  *
3428  *  \if ENABLE_EXAMPLES
3429  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3430  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3431  *  \endif
3432  */
3433 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3434 {
3435   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3436     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3437   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3438   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3439   std::size_t nbelems=std::distance(begin,end);
3440   int nbComp=getMeshDimension()+1;
3441   array->alloc((int)nbelems,nbComp);
3442   double *vals=array->getPointer();
3443   const int *connI=_nodal_connec_index->getConstPointer();
3444   const int *conn=_nodal_connec->getConstPointer();
3445   const double *coords=_coords->getConstPointer();
3446   if(getMeshDimension()==2)
3447     {
3448       if(getSpaceDimension()==3)
3449         {
3450           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3451           const double *locPtr=loc->getConstPointer();
3452           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3453             {
3454               int offset=connI[*i];
3455               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3456               double n=INTERP_KERNEL::norm<3>(vals);
3457               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3458             }
3459         }
3460       else
3461         {
3462           for(std::size_t i=0;i<nbelems;i++)
3463             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3464         }
3465     }
3466   else//meshdimension==1
3467     {
3468       double tmp[2];
3469       for(const int *i=begin;i!=end;i++)
3470         {
3471           int offset=connI[*i];
3472           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3473           double n=INTERP_KERNEL::norm<2>(tmp);
3474           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3475           *vals++=-tmp[1];
3476           *vals++=tmp[0];
3477         }
3478     }
3479   ret->setArray(array);
3480   ret->setMesh(this);
3481   ret->synchronizeTimeWithSupport();
3482   return ret.retn();
3483 }
3484
3485 /*!
3486  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3487  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3488  * and are \b not normalized.
3489  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3490  *          cells and one time. The caller is to delete this field using decrRef() as
3491  *          it is no more needed.
3492  *  \throw If the nodal connectivity of cells is not defined.
3493  *  \throw If the coordinates array is not set.
3494  *  \throw If \a this->getMeshDimension() != 1.
3495  *  \throw If \a this mesh includes cells of type other than SEG2.
3496  */
3497 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3498 {
3499   if(getMeshDimension()!=1)
3500     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3501   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3502     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3503   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3504   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3505   int nbOfCells=getNumberOfCells();
3506   int spaceDim=getSpaceDimension();
3507   array->alloc(nbOfCells,spaceDim);
3508   double *pt=array->getPointer();
3509   const double *coo=getCoords()->getConstPointer();
3510   std::vector<int> conn;
3511   conn.reserve(2);
3512   for(int i=0;i<nbOfCells;i++)
3513     {
3514       conn.resize(0);
3515       getNodeIdsOfCell(i,conn);
3516       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3517     }
3518   ret->setArray(array);
3519   ret->setMesh(this);
3520   ret->synchronizeTimeWithSupport();
3521   return ret.retn();
3522 }
3523
3524 /*!
3525  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3526  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3527  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3528  * from. If a result face is shared by two 3D cells, then the face in included twice in
3529  * the result mesh.
3530  *  \param [in] origin - 3 components of a point defining location of the plane.
3531  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3532  *         must be greater than 1e-6.
3533  *  \param [in] eps - half-thickness of the plane.
3534  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3535  *         producing correspondent 2D cells. The caller is to delete this array
3536  *         using decrRef() as it is no more needed.
3537  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3538  *         not share the node coordinates array with \a this mesh. The caller is to
3539  *         delete this mesh using decrRef() as it is no more needed.  
3540  *  \throw If the coordinates array is not set.
3541  *  \throw If the nodal connectivity of cells is not defined.
3542  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3543  *  \throw If magnitude of \a vec is less than 1e-6.
3544  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3545  *  \throw If \a this includes quadratic cells.
3546  */
3547 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3548 {
3549   checkFullyDefined();
3550   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3551     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3552   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3553   if(candidates->empty())
3554     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3555   std::vector<int> nodes;
3556   DataArrayInt *cellIds1D=0;
3557   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3558   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3559   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3560   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3561   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3562   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3563   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3564   revDesc2=0; revDescIndx2=0;
3565   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3566   revDesc1=0; revDescIndx1=0;
3567   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3568   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3569   //
3570   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3571   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3572     cut3DCurve[*it]=-1;
3573   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3574   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3575   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3576                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3577                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3578   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3579   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3580   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3581   if(cellIds2->empty())
3582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3583   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3584   ret->setCoords(mDesc1->getCoords());
3585   ret->setConnectivity(conn,connI,true);
3586   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3587   return ret.retn();
3588 }
3589
3590 /*!
3591  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3592 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
3593 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3594 the result mesh.
3595  *  \param [in] origin - 3 components of a point defining location of the plane.
3596  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3597  *         must be greater than 1e-6.
3598  *  \param [in] eps - half-thickness of the plane.
3599  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3600  *         producing correspondent segments. The caller is to delete this array
3601  *         using decrRef() as it is no more needed.
3602  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3603  *         mesh in 3D space. This mesh does not share the node coordinates array with
3604  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3605  *         no more needed. 
3606  *  \throw If the coordinates array is not set.
3607  *  \throw If the nodal connectivity of cells is not defined.
3608  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3609  *  \throw If magnitude of \a vec is less than 1e-6.
3610  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3611  *  \throw If \a this includes quadratic cells.
3612  */
3613 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3614 {
3615   checkFullyDefined();
3616   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3618   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3619   if(candidates->empty())
3620     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3621   std::vector<int> nodes;
3622   DataArrayInt *cellIds1D(0);
3623   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3624   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3625   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3626   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3627   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3628   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3629   //
3630   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3631   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3632     cut3DCurve[*it]=-1;
3633   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3634   int ncellsSub=subMesh->getNumberOfCells();
3635   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3636   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3637                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3638                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3639   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3640   conn->alloc(0,1);
3641   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3642   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3643   for(int i=0;i<ncellsSub;i++)
3644     {
3645       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3646         {
3647           if(cut3DSurf[i].first!=-2)
3648             {
3649               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3650               connI->pushBackSilent(conn->getNumberOfTuples());
3651               cellIds2->pushBackSilent(i);
3652             }
3653           else
3654             {
3655               int cellId3DSurf=cut3DSurf[i].second;
3656               int offset=nodalI[cellId3DSurf]+1;
3657               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3658               for(int j=0;j<nbOfEdges;j++)
3659                 {
3660                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3661                   connI->pushBackSilent(conn->getNumberOfTuples());
3662                   cellIds2->pushBackSilent(cellId3DSurf);
3663                 }
3664             }
3665         }
3666     }
3667   if(cellIds2->empty())
3668     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3669   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3670   ret->setCoords(mDesc1->getCoords());
3671   ret->setConnectivity(conn,connI,true);
3672   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3673   return ret.retn();
3674 }
3675
3676 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3677 {
3678   checkFullyDefined();
3679   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3680     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3681   if(getNumberOfCells()!=1)
3682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3683   //
3684   std::vector<int> nodes;
3685   findNodesOnPlane(origin,vec,eps,nodes);
3686   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());
3687   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3688   revDesc2=0; revDescIndx2=0;
3689   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3690   revDesc1=0; revDescIndx1=0;
3691   DataArrayInt *cellIds1D(0);
3692   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3693   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3694   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3695   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3696     cut3DCurve[*it]=-1;
3697   bool sameNbNodes;
3698   {
3699     int oldNbNodes(mDesc1->getNumberOfNodes());
3700     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3701     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3702   }
3703   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3704   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3705                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3706                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3707   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3708   connI->pushBackSilent(0); conn->alloc(0,1);
3709   {
3710     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3711     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3712     if(cellIds2->empty())
3713       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3714   }
3715   std::vector<std::vector<int> > res;
3716   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3717   std::size_t sz(res.size());
3718   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3720   for(std::size_t i=0;i<sz;i++)
3721     {
3722       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3723       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3724       connI->pushBackSilent(conn->getNumberOfTuples());
3725     }
3726   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3727   ret->setCoords(mDesc1->getCoords());
3728   ret->setConnectivity(conn,connI,true);
3729   int nbCellsRet(ret->getNumberOfCells());
3730   //
3731   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3732   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3733   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3734   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3735   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3736   MCAuto<DataArrayDouble> occm;
3737   {
3738     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3739     occm=DataArrayDouble::Substract(ccm,pt);
3740   }
3741   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3742   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);
3743   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3744   //
3745   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3746   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3747   ret2->setCoords(mDesc1->getCoords());
3748   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3749   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3750   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3751   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3752   if(dott->getIJ(0,0)>0)
3753     {
3754       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3755       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3756     }
3757   else
3758     {
3759       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3760       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3761     }
3762   for(int i=1;i<nbCellsRet;i++)
3763     {
3764       if(dott2->getIJ(i,0)<0)
3765         {
3766           if(ciPtr[i+1]-ciPtr[i]>=4)
3767             {
3768               cell0.push_back(-1);
3769               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3770             }
3771         }
3772       else
3773         {
3774           if(ciPtr[i+1]-ciPtr[i]>=4)
3775             {
3776               cell1.push_back(-1);
3777               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3778             }
3779         }
3780     }
3781   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3782   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3783   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3784   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3785   ret2->setConnectivity(conn2,conn2I,true);
3786   ret2->checkConsistencyLight();
3787   ret2->orientCorrectlyPolyhedrons();
3788   return ret2;
3789 }
3790
3791 /*!
3792  * Finds cells whose bounding boxes intersect a given plane.
3793  *  \param [in] origin - 3 components of a point defining location of the plane.
3794  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3795  *         must be greater than 1e-6.
3796  *  \param [in] eps - half-thickness of the plane.
3797  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3798  *         cells. The caller is to delete this array using decrRef() as it is no more
3799  *         needed.
3800  *  \throw If the coordinates array is not set.
3801  *  \throw If the nodal connectivity of cells is not defined.
3802  *  \throw If \a this->getSpaceDimension() != 3.
3803  *  \throw If magnitude of \a vec is less than 1e-6.
3804  *  \sa buildSlice3D()
3805  */
3806 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3807 {
3808   checkFullyDefined();
3809   if(getSpaceDimension()!=3)
3810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3811   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3812   if(normm<1e-6)
3813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3814   double vec2[3];
3815   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3816   double angle=acos(vec[2]/normm);
3817   MCAuto<DataArrayInt> cellIds;
3818   double bbox[6];
3819   if(angle>eps)
3820     {
3821       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3822       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3823       if(normm2/normm>1e-6)
3824         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3825       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3826       mw->setCoords(coo);
3827       mw->getBoundingBox(bbox);
3828       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3829       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3830     }
3831   else
3832     {
3833       getBoundingBox(bbox);
3834       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3835       cellIds=getCellsInBoundingBox(bbox,eps);
3836     }
3837   return cellIds.retn();
3838 }
3839
3840 /*!
3841  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3842  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3843  * No consideration of coordinate is done by this method.
3844  * 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)
3845  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3846  */
3847 bool MEDCouplingUMesh::isContiguous1D() const
3848 {
3849   if(getMeshDimension()!=1)
3850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3851   int nbCells=getNumberOfCells();
3852   if(nbCells<1)
3853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3854   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3855   int ref=conn[connI[0]+2];
3856   for(int i=1;i<nbCells;i++)
3857     {
3858       if(conn[connI[i]+1]!=ref)
3859         return false;
3860       ref=conn[connI[i]+2];
3861     }
3862   return true;
3863 }
3864
3865 /*!
3866  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3867  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3868  * \param pt reference point of the line
3869  * \param v normalized director vector of the line
3870  * \param eps max precision before throwing an exception
3871  * \param res output of size this->getNumberOfCells
3872  */
3873 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3874 {
3875   if(getMeshDimension()!=1)
3876     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3877   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3878     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3879   if(getSpaceDimension()!=3)
3880     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3881   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3882   const double *fPtr=f->getArray()->getConstPointer();
3883   double tmp[3];
3884   for(int i=0;i<getNumberOfCells();i++)
3885     {
3886       const double *tmp1=fPtr+3*i;
3887       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3888       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3889       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3890       double n1=INTERP_KERNEL::norm<3>(tmp);
3891       n1/=INTERP_KERNEL::norm<3>(tmp1);
3892       if(n1>eps)
3893         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3894     }
3895   const double *coo=getCoords()->getConstPointer();
3896   for(int i=0;i<getNumberOfNodes();i++)
3897     {
3898       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3899       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3900       res[i]=std::accumulate(tmp,tmp+3,0.);
3901     }
3902 }
3903
3904 /*!
3905  * 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. 
3906  * \a this is expected to be a mesh so that its space dimension is equal to its
3907  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3908  * 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).
3909  *
3910  * 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
3911  * 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).
3912  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3913  *
3914  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3915  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3916  *
3917  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3918  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3919  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3920  * \return the positive value of the distance.
3921  * \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
3922  * dimension - 1.
3923  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3924  */
3925 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3926 {
3927   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3928   if(meshDim!=spaceDim-1)
3929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3930   if(meshDim!=2 && meshDim!=1)
3931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3932   checkFullyDefined();
3933   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3934     { 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()); }
3935   DataArrayInt *ret1=0;
3936   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3937   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3938   MCAuto<DataArrayInt> ret1Safe(ret1);
3939   cellId=*ret1Safe->begin();
3940   return *ret0->begin();
3941 }
3942
3943 /*!
3944  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3945  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3946  * 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
3947  * 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).
3948  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3949  * 
3950  * \a this is expected to be a mesh so that its space dimension is equal to its
3951  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3952  * 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).
3953  *
3954  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3955  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3956  *
3957  * \param [in] pts the list of points in which each tuple represents a point
3958  * \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.
3959  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3960  * \throw if number of components of \a pts is not equal to the space dimension.
3961  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3962  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3963  */
3964 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3965 {
3966   if(!pts)
3967     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3968   pts->checkAllocated();
3969   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3970   if(meshDim!=spaceDim-1)
3971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3972   if(meshDim!=2 && meshDim!=1)
3973     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3974   if(pts->getNumberOfComponents()!=spaceDim)
3975     {
3976       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3977       throw INTERP_KERNEL::Exception(oss.str());
3978     }
3979   checkFullyDefined();
3980   int nbCells=getNumberOfCells();
3981   if(nbCells==0)
3982     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3983   int nbOfPts=pts->getNumberOfTuples();
3984   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3985   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3986   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3987   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3988   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3989   const double *bbox(bboxArr->begin());
3990   switch(spaceDim)
3991   {
3992     case 3:
3993       {
3994         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3995         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3996           {
3997             double x=std::numeric_limits<double>::max();
3998             std::vector<int> elems;
3999             myTree.getMinDistanceOfMax(ptsPtr,x);
4000             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4001             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4002           }
4003         break;
4004       }
4005     case 2:
4006       {
4007         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4008         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4009           {
4010             double x=std::numeric_limits<double>::max();
4011             std::vector<int> elems;
4012             myTree.getMinDistanceOfMax(ptsPtr,x);
4013             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4014             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4015           }
4016         break;
4017       }
4018     default:
4019       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4020   }
4021   cellIds=ret1.retn();
4022   return ret0.retn();
4023 }
4024
4025 /// @cond INTERNAL
4026
4027 /// @endcond
4028
4029 /*!
4030  * Finds cells in contact with a ball (i.e. a point with precision). 
4031  * 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.
4032  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4033  *
4034  * \warning This method is suitable if the caller intends to evaluate only one
4035  *          point, for more points getCellsContainingPoints() is recommended as it is
4036  *          faster. 
4037  *  \param [in] pos - array of coordinates of the ball central point.
4038  *  \param [in] eps - ball radius.
4039  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4040  *         if there are no such cells.
4041  *  \throw If the coordinates array is not set.
4042  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4043  */
4044 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4045 {
4046   std::vector<int> elts;
4047   getCellsContainingPoint(pos,eps,elts);
4048   if(elts.empty())
4049     return -1;
4050   return elts.front();
4051 }
4052
4053 /*!
4054  * Finds cells in contact with a ball (i.e. a point with precision).
4055  * 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.
4056  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4057  * \warning This method is suitable if the caller intends to evaluate only one
4058  *          point, for more points getCellsContainingPoints() is recommended as it is
4059  *          faster. 
4060  *  \param [in] pos - array of coordinates of the ball central point.
4061  *  \param [in] eps - ball radius.
4062  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4063  *         before inserting ids.
4064  *  \throw If the coordinates array is not set.
4065  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4066  *
4067  *  \if ENABLE_EXAMPLES
4068  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4069  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4070  *  \endif
4071  */
4072 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4073 {
4074   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4075   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4076   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4077 }
4078
4079 /*!
4080  * Finds cells in contact with several balls (i.e. points with precision).
4081  * This method is an extension of getCellContainingPoint() and
4082  * getCellsContainingPoint() for the case of multiple points.
4083  * 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.
4084  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4085  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4086  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4087  *         this->getSpaceDimension() * \a nbOfPoints 
4088  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4089  *  \param [in] eps - radius of balls (i.e. the precision).
4090  *  \param [out] elts - vector returning ids of found cells.
4091  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4092  *         dividing cell ids in \a elts into groups each referring to one
4093  *         point. Its every element (except the last one) is an index pointing to the
4094  *         first id of a group of cells. For example cells in contact with the *i*-th
4095  *         point are described by following range of indices:
4096  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4097  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4098  *         Number of cells in contact with the *i*-th point is
4099  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4100  *  \throw If the coordinates array is not set.
4101  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4102  *
4103  *  \if ENABLE_EXAMPLES
4104  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4105  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4106  *  \endif
4107  */
4108 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4109                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4110 {
4111   int spaceDim=getSpaceDimension();
4112   int mDim=getMeshDimension();
4113   if(spaceDim==3)
4114     {
4115       if(mDim==3)
4116         {
4117           const double *coords=_coords->getConstPointer();
4118           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4119         }
4120       /*else if(mDim==2)
4121         {
4122
4123         }*/
4124       else
4125         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4126     }
4127   else if(spaceDim==2)
4128     {
4129       if(mDim==2)
4130         {
4131           const double *coords=_coords->getConstPointer();
4132           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4133         }
4134       else
4135         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4136     }
4137   else if(spaceDim==1)
4138     {
4139       if(mDim==1)
4140         {
4141           const double *coords=_coords->getConstPointer();
4142           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4143         }
4144       else
4145         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4146     }
4147   else
4148     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4149 }
4150
4151 /*!
4152  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4153  * least two its edges intersect each other anywhere except their extremities. An
4154  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4155  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4156  *         cleared before filling in.
4157  *  \param [in] eps - precision.
4158  *  \throw If \a this->getMeshDimension() != 2.
4159  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4160  */
4161 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4162 {
4163   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4164   if(getMeshDimension()!=2)
4165     throw INTERP_KERNEL::Exception(msg);
4166   int spaceDim=getSpaceDimension();
4167   if(spaceDim!=2 && spaceDim!=3)
4168     throw INTERP_KERNEL::Exception(msg);
4169   const int *conn=_nodal_connec->getConstPointer();
4170   const int *connI=_nodal_connec_index->getConstPointer();
4171   int nbOfCells=getNumberOfCells();
4172   std::vector<double> cell2DinS2;
4173   for(int i=0;i<nbOfCells;i++)
4174     {
4175       int offset=connI[i];
4176       int nbOfNodesForCell=connI[i+1]-offset-1;
4177       if(nbOfNodesForCell<=3)
4178         continue;
4179       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4180       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4181       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4182         cells.push_back(i);
4183       cell2DinS2.clear();
4184     }
4185 }
4186
4187 /*!
4188  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4189  *
4190  * 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.
4191  * 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.
4192  * 
4193  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4194  * This convex envelop is computed using Jarvis march algorithm.
4195  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4196  * 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)
4197  * 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.
4198  *
4199  * \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.
4200  * \sa MEDCouplingUMesh::colinearize2D
4201  */
4202 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4203 {
4204   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4206   checkFullyDefined();
4207   const double *coords=getCoords()->getConstPointer();
4208   int nbOfCells=getNumberOfCells();
4209   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4210   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4211   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4212   int *workIndexOut=nodalConnecIndexOut->getPointer();
4213   *workIndexOut=0;
4214   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4215   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4216   std::set<INTERP_KERNEL::NormalizedCellType> types;
4217   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4218   isChanged->alloc(0,1);
4219   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4220     {
4221       int pos=nodalConnecOut->getNumberOfTuples();
4222       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4223         isChanged->pushBackSilent(i);
4224       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4225       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4226     }
4227   if(isChanged->empty())
4228     return 0;
4229   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4230   _types=types;
4231   return isChanged.retn();
4232 }
4233
4234 /*!
4235  * This method is \b NOT const because it can modify \a this.
4236  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4237  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4238  * \param policy specifies the type of extrusion chosen:
4239  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4240  *   will be repeated to build each level
4241  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4242  *   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
4243  *   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
4244  *   arc.
4245  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4246  */
4247 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4248 {
4249   checkFullyDefined();
4250   mesh1D->checkFullyDefined();
4251   if(!mesh1D->isContiguous1D())
4252     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4253   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4254     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4255   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4256     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4257   if(mesh1D->getMeshDimension()!=1)
4258     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4259   bool isQuad=false;
4260   if(isPresenceOfQuadratic())
4261     {
4262       if(mesh1D->isFullyQuadratic())
4263         isQuad=true;
4264       else
4265         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4266     }
4267   int oldNbOfNodes(getNumberOfNodes());
4268   MCAuto<DataArrayDouble> newCoords;
4269   switch(policy)
4270   {
4271     case 0:
4272       {
4273         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4274         break;
4275       }
4276     case 1:
4277       {
4278         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4279         break;
4280       }
4281     default:
4282       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4283   }
4284   setCoords(newCoords);
4285   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4286   updateTime();
4287   return ret.retn();
4288 }
4289
4290
4291 /*!
4292  * Checks if \a this mesh is constituted by only quadratic cells.
4293  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4294  *  \throw If the coordinates array is not set.
4295  *  \throw If the nodal connectivity of cells is not defined.
4296  */
4297 bool MEDCouplingUMesh::isFullyQuadratic() const
4298 {
4299   checkFullyDefined();
4300   bool ret=true;
4301   int nbOfCells=getNumberOfCells();
4302   for(int i=0;i<nbOfCells && ret;i++)
4303     {
4304       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4305       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4306       ret=cm.isQuadratic();
4307     }
4308   return ret;
4309 }
4310
4311 /*!
4312  * Checks if \a this mesh includes any quadratic cell.
4313  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4314  *  \throw If the coordinates array is not set.
4315  *  \throw If the nodal connectivity of cells is not defined.
4316  */
4317 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4318 {
4319   checkFullyDefined();
4320   bool ret=false;
4321   int nbOfCells=getNumberOfCells();
4322   for(int i=0;i<nbOfCells && !ret;i++)
4323     {
4324       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4325       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4326       ret=cm.isQuadratic();
4327     }
4328   return ret;
4329 }
4330
4331 /*!
4332  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4333  * this mesh, it remains unchanged.
4334  *  \throw If the coordinates array is not set.
4335  *  \throw If the nodal connectivity of cells is not defined.
4336  */
4337 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4338 {
4339   checkFullyDefined();
4340   int nbOfCells(getNumberOfCells());
4341   int delta=0;
4342   const int *iciptr=_nodal_connec_index->begin();
4343   for(int i=0;i<nbOfCells;i++)
4344     {
4345       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4346       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4347       if(cm.isQuadratic())
4348         {
4349           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4350           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4351           if(!cml.isDynamic())
4352             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4353           else
4354             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4355         }
4356     }
4357   if(delta==0)
4358     return ;
4359   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4360   const int *icptr(_nodal_connec->begin());
4361   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4362   newConnI->alloc(nbOfCells+1,1);
4363   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4364   *ociptr=0;
4365   _types.clear();
4366   for(int i=0;i<nbOfCells;i++,ociptr++)
4367     {
4368       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4369       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4370       if(!cm.isQuadratic())
4371         {
4372           _types.insert(type);
4373           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4374           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4375         }
4376       else
4377         {
4378           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4379           _types.insert(typel);
4380           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4381           int newNbOfNodes=cml.getNumberOfNodes();
4382           if(cml.isDynamic())
4383             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4384           *ocptr++=(int)typel;
4385           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4386           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4387         }
4388     }
4389   setConnectivity(newConn,newConnI,false);
4390 }
4391
4392 /*!
4393  * This method converts all linear cell in \a this to quadratic one.
4394  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4395  * 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)
4396  * 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.
4397  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4398  * end of the existing coordinates.
4399  * 
4400  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4401  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4402  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4403  * 
4404  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4405  *
4406  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4407  */
4408 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4409 {
4410   DataArrayInt *conn=0,*connI=0;
4411   DataArrayDouble *coords=0;
4412   std::set<INTERP_KERNEL::NormalizedCellType> types;
4413   checkFullyDefined();
4414   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4415   MCAuto<DataArrayDouble> coordsSafe;
4416   int meshDim=getMeshDimension();
4417   switch(conversionType)
4418   {
4419     case 0:
4420       switch(meshDim)
4421       {
4422         case 1:
4423           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4424           connSafe=conn; connISafe=connI; coordsSafe=coords;
4425           break;
4426         case 2:
4427           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4428           connSafe=conn; connISafe=connI; coordsSafe=coords;
4429           break;
4430         case 3:
4431           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4432           connSafe=conn; connISafe=connI; coordsSafe=coords;
4433           break;
4434         default:
4435           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4436       }
4437       break;
4438         case 1:
4439           {
4440             switch(meshDim)
4441             {
4442               case 1:
4443                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4444                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4445                 break;
4446               case 2:
4447                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4448                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4449                 break;
4450               case 3:
4451                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4452                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4453                 break;
4454               default:
4455                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4456             }
4457             break;
4458           }
4459         default:
4460           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4461   }
4462   setConnectivity(connSafe,connISafe,false);
4463   _types=types;
4464   setCoords(coordsSafe);
4465   return ret.retn();
4466 }
4467
4468 /*!
4469  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4470  * so that the number of cells remains the same. Quadratic faces are converted to
4471  * polygons. This method works only for 2D meshes in
4472  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4473  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4474  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4475  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4476  *         a polylinized edge constituting the input polygon.
4477  *  \throw If the coordinates array is not set.
4478  *  \throw If the nodal connectivity of cells is not defined.
4479  *  \throw If \a this->getMeshDimension() != 2.
4480  *  \throw If \a this->getSpaceDimension() != 2.
4481  */
4482 void MEDCouplingUMesh::tessellate2D(double eps)
4483 {
4484   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4485   if(spaceDim!=2)
4486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4487   switch(meshDim)
4488     {
4489     case 1:
4490       return tessellate2DCurveInternal(eps);
4491     case 2:
4492       return tessellate2DInternal(eps);
4493     default:
4494       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4495     }
4496 }
4497 /*!
4498  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4499  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4500  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4501  *         a sub-divided edge.
4502  *  \throw If the coordinates array is not set.
4503  *  \throw If the nodal connectivity of cells is not defined.
4504  *  \throw If \a this->getMeshDimension() != 1.
4505  *  \throw If \a this->getSpaceDimension() != 2.
4506  */
4507
4508 #if 0
4509 /*!
4510  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4511  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4512  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4513  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4514  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4515  * This method can be seen as the opposite method of colinearize2D.
4516  * 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
4517  * to avoid to modify the numbering of existing nodes.
4518  *
4519  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4520  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4521  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4522  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4523  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4524  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4525  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4526  *
4527  * \sa buildDescendingConnectivity2
4528  */
4529 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4530                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4531 {
4532   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4534   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4535   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4537   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4539   //DataArrayInt *out0(0),*outi0(0);
4540   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4541   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4542   //out0s=out0s->buildUnique(); out0s->sort(true);
4543 }
4544 #endif
4545
4546
4547 /*!
4548  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4549  * In addition, returns an array mapping new cells to old ones. <br>
4550  * This method typically increases the number of cells in \a this mesh
4551  * but the number of nodes remains \b unchanged.
4552  * That's why the 3D splitting policies
4553  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4554  *  \param [in] policy - specifies a pattern used for splitting.
4555  * The semantic of \a policy is:
4556  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4557  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4558  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4559  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4560  *
4561  *
4562  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4563  *          an id of old cell producing it. The caller is to delete this array using
4564  *         decrRef() as it is no more needed.
4565  *
4566  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4567  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4568  *          and \a this->getMeshDimension() != 3. 
4569  *  \throw If \a policy is not one of the four discussed above.
4570  *  \throw If the nodal connectivity of cells is not defined.
4571  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4572  */
4573 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4574 {
4575   switch(policy)
4576   {
4577     case 0:
4578       return simplexizePol0();
4579     case 1:
4580       return simplexizePol1();
4581     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4582         return simplexizePlanarFace5();
4583     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4584         return simplexizePlanarFace6();
4585     default:
4586       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)");
4587   }
4588 }
4589
4590 /*!
4591  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4592  * - 1D: INTERP_KERNEL::NORM_SEG2
4593  * - 2D: INTERP_KERNEL::NORM_TRI3
4594  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4595  *
4596  * This method is useful for users that need to use P1 field services as
4597  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4598  * All these methods need mesh support containing only simplex cells.
4599  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4600  *  \throw If the coordinates array is not set.
4601  *  \throw If the nodal connectivity of cells is not defined.
4602  *  \throw If \a this->getMeshDimension() < 1.
4603  */
4604 bool MEDCouplingUMesh::areOnlySimplexCells() const
4605 {
4606   checkFullyDefined();
4607   int mdim=getMeshDimension();
4608   if(mdim<1 || mdim>3)
4609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4610   int nbCells=getNumberOfCells();
4611   const int *conn=_nodal_connec->begin();
4612   const int *connI=_nodal_connec_index->begin();
4613   for(int i=0;i<nbCells;i++)
4614     {
4615       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4616       if(!cm.isSimplex())
4617         return false;
4618     }
4619   return true;
4620 }
4621
4622
4623
4624 /*!
4625  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4626  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4627  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
4628  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
4629  * so it can be useful to call mergeNodes() before calling this method.
4630  *  \throw If \a this->getMeshDimension() <= 1.
4631  *  \throw If the coordinates array is not set.
4632  *  \throw If the nodal connectivity of cells is not defined.
4633  */
4634 void MEDCouplingUMesh::convertDegeneratedCells()
4635 {
4636   checkFullyDefined();
4637   if(getMeshDimension()<=1)
4638     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4639   int nbOfCells=getNumberOfCells();
4640   if(nbOfCells<1)
4641     return ;
4642   int initMeshLgth=getNodalConnectivityArrayLen();
4643   int *conn=_nodal_connec->getPointer();
4644   int *index=_nodal_connec_index->getPointer();
4645   int posOfCurCell=0;
4646   int newPos=0;
4647   int lgthOfCurCell;
4648   for(int i=0;i<nbOfCells;i++)
4649     {
4650       lgthOfCurCell=index[i+1]-posOfCurCell;
4651       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4652       int newLgth;
4653       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4654                                                                                                      conn+newPos+1,newLgth);
4655       conn[newPos]=newType;
4656       newPos+=newLgth+1;
4657       posOfCurCell=index[i+1];
4658       index[i+1]=newPos;
4659     }
4660   if(newPos!=initMeshLgth)
4661     _nodal_connec->reAlloc(newPos);
4662   computeTypes();
4663 }
4664
4665 /*!
4666  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4667  * A cell is considered to be oriented correctly if an angle between its
4668  * normal vector and a given vector is less than \c PI / \c 2.
4669  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4670  *         cells. 
4671  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4672  *         checked.
4673  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4674  *         is not cleared before filling in.
4675  *  \throw If \a this->getMeshDimension() != 2.
4676  *  \throw If \a this->getSpaceDimension() != 3.
4677  *
4678  *  \if ENABLE_EXAMPLES
4679  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4680  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4681  *  \endif
4682  */
4683 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4684 {
4685   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4686     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4687   int nbOfCells=getNumberOfCells();
4688   const int *conn=_nodal_connec->begin();
4689   const int *connI=_nodal_connec_index->begin();
4690   const double *coordsPtr=_coords->begin();
4691   for(int i=0;i<nbOfCells;i++)
4692     {
4693       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4694       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4695         {
4696           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4697           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4698             cells.push_back(i);
4699         }
4700     }
4701 }
4702
4703 /*!
4704  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4705  * considered to be oriented correctly if an angle between its normal vector and a
4706  * given vector is less than \c PI / \c 2. 
4707  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4708  *         cells. 
4709  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4710  *         checked.
4711  *  \throw If \a this->getMeshDimension() != 2.
4712  *  \throw If \a this->getSpaceDimension() != 3.
4713  *
4714  *  \if ENABLE_EXAMPLES
4715  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4716  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4717  *  \endif
4718  *
4719  *  \sa changeOrientationOfCells
4720  */
4721 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4722 {
4723   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4724     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4725   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4726   const int *connI(_nodal_connec_index->begin());
4727   const double *coordsPtr(_coords->begin());
4728   bool isModified(false);
4729   for(int i=0;i<nbOfCells;i++)
4730     {
4731       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4732       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4733         {
4734           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4735           bool isQuadratic(cm.isQuadratic());
4736           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4737             {
4738               isModified=true;
4739               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4740             }
4741         }
4742     }
4743   if(isModified)
4744     _nodal_connec->declareAsNew();
4745   updateTime();
4746 }
4747
4748 /*!
4749  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4750  *
4751  * \sa orientCorrectly2DCells
4752  */
4753 void MEDCouplingUMesh::changeOrientationOfCells()
4754 {
4755   int mdim(getMeshDimension());
4756   if(mdim!=2 && mdim!=1)
4757     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4758   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4759   const int *connI(_nodal_connec_index->begin());
4760   if(mdim==2)
4761     {//2D
4762       for(int i=0;i<nbOfCells;i++)
4763         {
4764           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4765           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4766           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4767         }
4768     }
4769   else
4770     {//1D
4771       for(int i=0;i<nbOfCells;i++)
4772         {
4773           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4774           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4775           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4776         }
4777     }
4778 }
4779
4780 /*!
4781  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4782  * oriented facets. The normal vector of the facet should point out of the cell.
4783  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4784  *         is not cleared before filling in.
4785  *  \throw If \a this->getMeshDimension() != 3.
4786  *  \throw If \a this->getSpaceDimension() != 3.
4787  *  \throw If the coordinates array is not set.
4788  *  \throw If the nodal connectivity of cells is not defined.
4789  *
4790  *  \if ENABLE_EXAMPLES
4791  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4792  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4793  *  \endif
4794  */
4795 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4796 {
4797   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4798     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4799   int nbOfCells=getNumberOfCells();
4800   const int *conn=_nodal_connec->begin();
4801   const int *connI=_nodal_connec_index->begin();
4802   const double *coordsPtr=_coords->begin();
4803   for(int i=0;i<nbOfCells;i++)
4804     {
4805       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4806       if(type==INTERP_KERNEL::NORM_POLYHED)
4807         {
4808           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4809             cells.push_back(i);
4810         }
4811     }
4812 }
4813
4814 /*!
4815  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4816  * out of the cell. 
4817  *  \throw If \a this->getMeshDimension() != 3.
4818  *  \throw If \a this->getSpaceDimension() != 3.
4819  *  \throw If the coordinates array is not set.
4820  *  \throw If the nodal connectivity of cells is not defined.
4821  *  \throw If the reparation fails.
4822  *
4823  *  \if ENABLE_EXAMPLES
4824  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4825  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4826  *  \endif
4827  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4828  */
4829 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4830 {
4831   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4832     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4833   int nbOfCells=getNumberOfCells();
4834   int *conn=_nodal_connec->getPointer();
4835   const int *connI=_nodal_connec_index->begin();
4836   const double *coordsPtr=_coords->begin();
4837   for(int i=0;i<nbOfCells;i++)
4838     {
4839       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4840       if(type==INTERP_KERNEL::NORM_POLYHED)
4841         {
4842           try
4843           {
4844               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4845                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4846           }
4847           catch(INTERP_KERNEL::Exception& e)
4848           {
4849               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4850               throw INTERP_KERNEL::Exception(oss.str());
4851           }
4852         }
4853     }
4854   updateTime();
4855 }
4856
4857 /*!
4858  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4859  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4860  * according to which the first facet of the cell should be oriented to have the normal vector
4861  * pointing out of cell.
4862  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4863  *         cells. The caller is to delete this array using decrRef() as it is no more
4864  *         needed. 
4865  *  \throw If \a this->getMeshDimension() != 3.
4866  *  \throw If \a this->getSpaceDimension() != 3.
4867  *  \throw If the coordinates array is not set.
4868  *  \throw If the nodal connectivity of cells is not defined.
4869  *
4870  *  \if ENABLE_EXAMPLES
4871  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
4872  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
4873  *  \endif
4874  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4875  */
4876 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
4877 {
4878   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
4879   if(getMeshDimension()!=3)
4880     throw INTERP_KERNEL::Exception(msg);
4881   int spaceDim=getSpaceDimension();
4882   if(spaceDim!=3)
4883     throw INTERP_KERNEL::Exception(msg);
4884   //
4885   int nbOfCells=getNumberOfCells();
4886   int *conn=_nodal_connec->getPointer();
4887   const int *connI=_nodal_connec_index->begin();
4888   const double *coo=getCoords()->begin();
4889   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
4890   for(int i=0;i<nbOfCells;i++)
4891     {
4892       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4893       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
4894         {
4895           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
4896             {
4897               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4898               cells->pushBackSilent(i);
4899             }
4900         }
4901     }
4902   return cells.retn();
4903 }
4904
4905 /*!
4906  * This method is a faster method to correct orientation of all 3D cells in \a this.
4907  * 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.
4908  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
4909  * 
4910  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
4911  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
4912  */
4913 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
4914 {
4915   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4916     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
4917   int nbOfCells=getNumberOfCells();
4918   int *conn=_nodal_connec->getPointer();
4919   const int *connI=_nodal_connec_index->begin();
4920   const double *coordsPtr=_coords->begin();
4921   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4922   for(int i=0;i<nbOfCells;i++)
4923     {
4924       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4925       switch(type)
4926       {
4927         case INTERP_KERNEL::NORM_TETRA4:
4928           {
4929             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4930               {
4931                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
4932                 ret->pushBackSilent(i);
4933               }
4934             break;
4935           }
4936         case INTERP_KERNEL::NORM_PYRA5:
4937           {
4938             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4939               {
4940                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
4941                 ret->pushBackSilent(i);
4942               }
4943             break;
4944           }
4945         case INTERP_KERNEL::NORM_PENTA6:
4946         case INTERP_KERNEL::NORM_HEXA8:
4947         case INTERP_KERNEL::NORM_HEXGP12:
4948           {
4949             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4950               {
4951                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4952                 ret->pushBackSilent(i);
4953               }
4954             break;
4955           }
4956         case INTERP_KERNEL::NORM_POLYHED:
4957           {
4958             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4959               {
4960                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4961                 ret->pushBackSilent(i);
4962               }
4963             break;
4964           }
4965         default:
4966           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 !");
4967       }
4968     }
4969   updateTime();
4970   return ret.retn();
4971 }
4972
4973 /*!
4974  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
4975  * If it is not the case an exception will be thrown.
4976  * This method is fast because the first cell of \a this is used to compute the plane.
4977  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
4978  * \param pos output of size at least 3 used to store a point owned of searched plane.
4979  */
4980 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
4981 {
4982   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4983     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
4984   const int *conn=_nodal_connec->begin();
4985   const int *connI=_nodal_connec_index->begin();
4986   const double *coordsPtr=_coords->begin();
4987   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
4988   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
4989 }
4990
4991 /*!
4992  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
4993  * cells. Currently cells of the following types are treated:
4994  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
4995  * For a cell of other type an exception is thrown.
4996  * Space dimension of a 2D mesh can be either 2 or 3.
4997  * The Edge Ratio of a cell \f$t\f$ is: 
4998  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
4999  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5000  *  the smallest edge lengths of \f$t\f$.
5001  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5002  *          cells and one time, lying on \a this mesh. The caller is to delete this
5003  *          field using decrRef() as it is no more needed. 
5004  *  \throw If the coordinates array is not set.
5005  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5006  *  \throw If the connectivity data array has more than one component.
5007  *  \throw If the connectivity data array has a named component.
5008  *  \throw If the connectivity index data array has more than one component.
5009  *  \throw If the connectivity index data array has a named component.
5010  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5011  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5012  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5013  */
5014 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5015 {
5016   checkConsistencyLight();
5017   int spaceDim=getSpaceDimension();
5018   int meshDim=getMeshDimension();
5019   if(spaceDim!=2 && spaceDim!=3)
5020     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5021   if(meshDim!=2 && meshDim!=3)
5022     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5023   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5024   ret->setMesh(this);
5025   int nbOfCells=getNumberOfCells();
5026   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5027   arr->alloc(nbOfCells,1);
5028   double *pt=arr->getPointer();
5029   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5030   const int *conn=_nodal_connec->begin();
5031   const int *connI=_nodal_connec_index->begin();
5032   const double *coo=_coords->begin();
5033   double tmp[12];
5034   for(int i=0;i<nbOfCells;i++,pt++)
5035     {
5036       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5037       switch(t)
5038       {
5039         case INTERP_KERNEL::NORM_TRI3:
5040           {
5041             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5042             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5043             break;
5044           }
5045         case INTERP_KERNEL::NORM_QUAD4:
5046           {
5047             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5048             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5049             break;
5050           }
5051         case INTERP_KERNEL::NORM_TETRA4:
5052           {
5053             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5054             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5055             break;
5056           }
5057         default:
5058           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5059       }
5060       conn+=connI[i+1]-connI[i];
5061     }
5062   ret->setName("EdgeRatio");
5063   ret->synchronizeTimeWithSupport();
5064   return ret.retn();
5065 }
5066
5067 /*!
5068  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5069  * cells. Currently cells of the following types are treated:
5070  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5071  * For a cell of other type an exception is thrown.
5072  * Space dimension of a 2D mesh can be either 2 or 3.
5073  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5074  *          cells and one time, lying on \a this mesh. The caller is to delete this
5075  *          field using decrRef() as it is no more needed. 
5076  *  \throw If the coordinates array is not set.
5077  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5078  *  \throw If the connectivity data array has more than one component.
5079  *  \throw If the connectivity data array has a named component.
5080  *  \throw If the connectivity index data array has more than one component.
5081  *  \throw If the connectivity index data array has a named component.
5082  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5083  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5084  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5085  */
5086 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5087 {
5088   checkConsistencyLight();
5089   int spaceDim=getSpaceDimension();
5090   int meshDim=getMeshDimension();
5091   if(spaceDim!=2 && spaceDim!=3)
5092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5093   if(meshDim!=2 && meshDim!=3)
5094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5095   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5096   ret->setMesh(this);
5097   int nbOfCells=getNumberOfCells();
5098   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5099   arr->alloc(nbOfCells,1);
5100   double *pt=arr->getPointer();
5101   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5102   const int *conn=_nodal_connec->begin();
5103   const int *connI=_nodal_connec_index->begin();
5104   const double *coo=_coords->begin();
5105   double tmp[12];
5106   for(int i=0;i<nbOfCells;i++,pt++)
5107     {
5108       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5109       switch(t)
5110       {
5111         case INTERP_KERNEL::NORM_TRI3:
5112           {
5113             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5114             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5115             break;
5116           }
5117         case INTERP_KERNEL::NORM_QUAD4:
5118           {
5119             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5120             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5121             break;
5122           }
5123         case INTERP_KERNEL::NORM_TETRA4:
5124           {
5125             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5126             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5127             break;
5128           }
5129         default:
5130           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5131       }
5132       conn+=connI[i+1]-connI[i];
5133     }
5134   ret->setName("AspectRatio");
5135   ret->synchronizeTimeWithSupport();
5136   return ret.retn();
5137 }
5138
5139 /*!
5140  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5141  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5142  * in 3D space. Currently only cells of the following types are
5143  * treated: INTERP_KERNEL::NORM_QUAD4.
5144  * For a cell of other type an exception is thrown.
5145  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5146  * Defining
5147  * \f$t=\vec{da}\times\vec{ab}\f$,
5148  * \f$u=\vec{ab}\times\vec{bc}\f$
5149  * \f$v=\vec{bc}\times\vec{cd}\f$
5150  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5151  *  \f[
5152  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5153  *  \f]
5154  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5155  *          cells and one time, lying on \a this mesh. The caller is to delete this
5156  *          field using decrRef() as it is no more needed. 
5157  *  \throw If the coordinates array is not set.
5158  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5159  *  \throw If the connectivity data array has more than one component.
5160  *  \throw If the connectivity data array has a named component.
5161  *  \throw If the connectivity index data array has more than one component.
5162  *  \throw If the connectivity index data array has a named component.
5163  *  \throw If \a this->getMeshDimension() != 2.
5164  *  \throw If \a this->getSpaceDimension() != 3.
5165  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5166  */
5167 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5168 {
5169   checkConsistencyLight();
5170   int spaceDim=getSpaceDimension();
5171   int meshDim=getMeshDimension();
5172   if(spaceDim!=3)
5173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5174   if(meshDim!=2)
5175     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5176   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5177   ret->setMesh(this);
5178   int nbOfCells=getNumberOfCells();
5179   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5180   arr->alloc(nbOfCells,1);
5181   double *pt=arr->getPointer();
5182   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5183   const int *conn=_nodal_connec->begin();
5184   const int *connI=_nodal_connec_index->begin();
5185   const double *coo=_coords->begin();
5186   double tmp[12];
5187   for(int i=0;i<nbOfCells;i++,pt++)
5188     {
5189       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5190       switch(t)
5191       {
5192         case INTERP_KERNEL::NORM_QUAD4:
5193           {
5194             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5195             *pt=INTERP_KERNEL::quadWarp(tmp);
5196             break;
5197           }
5198         default:
5199           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5200       }
5201       conn+=connI[i+1]-connI[i];
5202     }
5203   ret->setName("Warp");
5204   ret->synchronizeTimeWithSupport();
5205   return ret.retn();
5206 }
5207
5208
5209 /*!
5210  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5211  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5212  * treated: INTERP_KERNEL::NORM_QUAD4.
5213  * The skew is computed as follow for a quad with points (a,b,c,d): let
5214  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5215  * then the skew is computed as:
5216  *  \f[
5217  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5218  *  \f]
5219  *
5220  * For a cell of other type an exception is thrown.
5221  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5222  *          cells and one time, lying on \a this mesh. The caller is to delete this
5223  *          field using decrRef() as it is no more needed. 
5224  *  \throw If the coordinates array is not set.
5225  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5226  *  \throw If the connectivity data array has more than one component.
5227  *  \throw If the connectivity data array has a named component.
5228  *  \throw If the connectivity index data array has more than one component.
5229  *  \throw If the connectivity index data array has a named component.
5230  *  \throw If \a this->getMeshDimension() != 2.
5231  *  \throw If \a this->getSpaceDimension() != 3.
5232  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5233  */
5234 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5235 {
5236   checkConsistencyLight();
5237   int spaceDim=getSpaceDimension();
5238   int meshDim=getMeshDimension();
5239   if(spaceDim!=3)
5240     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5241   if(meshDim!=2)
5242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5243   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5244   ret->setMesh(this);
5245   int nbOfCells=getNumberOfCells();
5246   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5247   arr->alloc(nbOfCells,1);
5248   double *pt=arr->getPointer();
5249   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5250   const int *conn=_nodal_connec->begin();
5251   const int *connI=_nodal_connec_index->begin();
5252   const double *coo=_coords->begin();
5253   double tmp[12];
5254   for(int i=0;i<nbOfCells;i++,pt++)
5255     {
5256       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5257       switch(t)
5258       {
5259         case INTERP_KERNEL::NORM_QUAD4:
5260           {
5261             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5262             *pt=INTERP_KERNEL::quadSkew(tmp);
5263             break;
5264           }
5265         default:
5266           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5267       }
5268       conn+=connI[i+1]-connI[i];
5269     }
5270   ret->setName("Skew");
5271   ret->synchronizeTimeWithSupport();
5272   return ret.retn();
5273 }
5274
5275 /*!
5276  * 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.
5277  *
5278  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5279  *
5280  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5281  */
5282 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5283 {
5284   checkConsistencyLight();
5285   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5286   ret->setMesh(this);
5287   std::set<INTERP_KERNEL::NormalizedCellType> types;
5288   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5289   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5290   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5291   arr->alloc(nbCells,1);
5292   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5293     {
5294       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5295       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5296       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5297     }
5298   ret->setArray(arr);
5299   ret->setName("Diameter");
5300   return ret.retn();
5301 }
5302
5303 /*!
5304  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5305  * 
5306  * \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)
5307  *                         For all other cases this input parameter is ignored.
5308  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5309  * 
5310  * \throw If \a this is not fully set (coordinates and connectivity).
5311  * \throw If a cell in \a this has no valid nodeId.
5312  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5313  */
5314 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5315 {
5316   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5317   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.
5318     return getBoundingBoxForBBTreeFast();
5319   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5320     {
5321       bool presenceOfQuadratic(false);
5322       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5323         {
5324           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5325           if(cm.isQuadratic())
5326             presenceOfQuadratic=true;
5327         }
5328       if(!presenceOfQuadratic)
5329         return getBoundingBoxForBBTreeFast();
5330       if(mDim==2 && sDim==2)
5331         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5332       else
5333         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5334     }
5335   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) !");
5336 }
5337
5338 /*!
5339  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5340  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5341  * 
5342  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5343  * 
5344  * \throw If \a this is not fully set (coordinates and connectivity).
5345  * \throw If a cell in \a this has no valid nodeId.
5346  */
5347 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5348 {
5349   checkFullyDefined();
5350   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5351   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5352   double *bbox(ret->getPointer());
5353   for(int i=0;i<nbOfCells*spaceDim;i++)
5354     {
5355       bbox[2*i]=std::numeric_limits<double>::max();
5356       bbox[2*i+1]=-std::numeric_limits<double>::max();
5357     }
5358   const double *coordsPtr(_coords->begin());
5359   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5360   for(int i=0;i<nbOfCells;i++)
5361     {
5362       int offset=connI[i]+1;
5363       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5364       for(int j=0;j<nbOfNodesForCell;j++)
5365         {
5366           int nodeId=conn[offset+j];
5367           if(nodeId>=0 && nodeId<nbOfNodes)
5368             {
5369               for(int k=0;k<spaceDim;k++)
5370                 {
5371                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5372                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5373                 }
5374               kk++;
5375             }
5376         }
5377       if(kk==0)
5378         {
5379           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5380           throw INTERP_KERNEL::Exception(oss.str());
5381         }
5382     }
5383   return ret.retn();
5384 }
5385
5386 /*!
5387  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5388  * useful for 2D meshes having quadratic cells
5389  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5390  * the two extremities of the arc of circle).
5391  * 
5392  * \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)
5393  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5394  * \throw If \a this is not fully defined.
5395  * \throw If \a this is not a mesh with meshDimension equal to 2.
5396  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5397  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5398  */
5399 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5400 {
5401   checkFullyDefined();
5402   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5403   if(spaceDim!=2 || mDim!=2)
5404     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!");
5405   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5406   double *bbox(ret->getPointer());
5407   const double *coords(_coords->begin());
5408   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5409   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5410     {
5411       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5412       int sz(connI[1]-connI[0]-1);
5413       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
5414       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5415       INTERP_KERNEL::QuadraticPolygon *pol(0);
5416       for(int j=0;j<sz;j++)
5417         {
5418           int nodeId(conn[*connI+1+j]);
5419           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5420         }
5421       if(!cm.isQuadratic())
5422         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5423       else
5424         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5425       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5426       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5427     }
5428   return ret.retn();
5429 }
5430
5431 /*!
5432  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5433  * useful for 2D meshes having quadratic cells
5434  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5435  * the two extremities of the arc of circle).
5436  * 
5437  * \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)
5438  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5439  * \throw If \a this is not fully defined.
5440  * \throw If \a this is not a mesh with meshDimension equal to 1.
5441  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5442  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5443  */
5444 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5445 {
5446   checkFullyDefined();
5447   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5448   if(spaceDim!=2 || mDim!=1)
5449     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!");
5450   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5451   double *bbox(ret->getPointer());
5452   const double *coords(_coords->begin());
5453   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5454   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5455     {
5456       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5457       int sz(connI[1]-connI[0]-1);
5458       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
5459       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5460       INTERP_KERNEL::Edge *edge(0);
5461       for(int j=0;j<sz;j++)
5462         {
5463           int nodeId(conn[*connI+1+j]);
5464           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5465         }
5466       if(!cm.isQuadratic())
5467         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5468       else
5469         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5470       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5471       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5472     }
5473   return ret.retn();
5474 }
5475
5476 /// @cond INTERNAL
5477
5478 namespace MEDCouplingImpl
5479 {
5480   class ConnReader
5481   {
5482   public:
5483     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5484     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5485   private:
5486     const int *_conn;
5487     int _val;
5488   };
5489
5490   class ConnReader2
5491   {
5492   public:
5493     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5494     bool operator() (const int& pos) { return _conn[pos]==_val; }
5495   private:
5496     const int *_conn;
5497     int _val;
5498   };
5499 }
5500
5501 /// @endcond
5502
5503 /*!
5504  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5505  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5506  * \a this is composed in cell types.
5507  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5508  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5509  * This parameter is kept only for compatibility with other methode listed above.
5510  */
5511 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5512 {
5513   checkConnectivityFullyDefined();
5514   const int *conn=_nodal_connec->begin();
5515   const int *connI=_nodal_connec_index->begin();
5516   const int *work=connI;
5517   int nbOfCells=getNumberOfCells();
5518   std::size_t n=getAllGeoTypes().size();
5519   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5520   std::set<INTERP_KERNEL::NormalizedCellType> types;
5521   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5522     {
5523       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5524       if(types.find(typ)!=types.end())
5525         {
5526           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5527           oss << " is not contiguous !";
5528           throw INTERP_KERNEL::Exception(oss.str());
5529         }
5530       types.insert(typ);
5531       ret[3*i]=typ;
5532       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5533       ret[3*i+1]=(int)std::distance(work,work2);
5534       work=work2;
5535     }
5536   return ret;
5537 }
5538
5539 /*!
5540  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5541  * only for types cell, type node is not managed.
5542  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5543  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5544  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5545  * If 2 or more same geometric type is in \a code and exception is thrown too.
5546  *
5547  * This method firstly checks
5548  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5549  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5550  * an exception is thrown too.
5551  * 
5552  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5553  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5554  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5555  */
5556 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5557 {
5558   if(code.empty())
5559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5560   std::size_t sz=code.size();
5561   std::size_t n=sz/3;
5562   if(sz%3!=0)
5563     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5564   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5565   int nb=0;
5566   bool isNoPflUsed=true;
5567   for(std::size_t i=0;i<n;i++)
5568     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5569       {
5570         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5571         nb+=code[3*i+1];
5572         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5573           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5574         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5575       }
5576   if(types.size()!=n)
5577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5578   if(isNoPflUsed)
5579     {
5580       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5581         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5582       if(types.size()==_types.size())
5583         return 0;
5584     }
5585   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5586   ret->alloc(nb,1);
5587   int *retPtr=ret->getPointer();
5588   const int *connI=_nodal_connec_index->begin();
5589   const int *conn=_nodal_connec->begin();
5590   int nbOfCells=getNumberOfCells();
5591   const int *i=connI;
5592   int kk=0;
5593   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5594     {
5595       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5596       int offset=(int)std::distance(connI,i);
5597       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5598       int nbOfCellsOfCurType=(int)std::distance(i,j);
5599       if(code[3*kk+2]==-1)
5600         for(int k=0;k<nbOfCellsOfCurType;k++)
5601           *retPtr++=k+offset;
5602       else
5603         {
5604           int idInIdsPerType=code[3*kk+2];
5605           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5606             {
5607               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5608               if(zePfl)
5609                 {
5610                   zePfl->checkAllocated();
5611                   if(zePfl->getNumberOfComponents()==1)
5612                     {
5613                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5614                         {
5615                           if(*k>=0 && *k<nbOfCellsOfCurType)
5616                             *retPtr=(*k)+offset;
5617                           else
5618                             {
5619                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5620                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5621                               throw INTERP_KERNEL::Exception(oss.str());
5622                             }
5623                         }
5624                     }
5625                   else
5626                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5627                 }
5628               else
5629                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5630             }
5631           else
5632             {
5633               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5634               oss << " should be in [0," << idsPerType.size() << ") !";
5635               throw INTERP_KERNEL::Exception(oss.str());
5636             }
5637         }
5638       i=j;
5639     }
5640   return ret.retn();
5641 }
5642
5643 /*!
5644  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5645  * 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.
5646  * 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.
5647  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5648  * 
5649  * \param [in] profile
5650  * \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.
5651  * \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,
5652  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5653  * \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.
5654  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5655  * \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
5656  */
5657 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
5658 {
5659   if(!profile)
5660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5661   if(profile->getNumberOfComponents()!=1)
5662     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5663   checkConnectivityFullyDefined();
5664   const int *conn=_nodal_connec->begin();
5665   const int *connI=_nodal_connec_index->begin();
5666   int nbOfCells=getNumberOfCells();
5667   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5668   std::vector<int> typeRangeVals(1);
5669   for(const int *i=connI;i!=connI+nbOfCells;)
5670     {
5671       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5672       if(std::find(types.begin(),types.end(),curType)!=types.end())
5673         {
5674           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5675         }
5676       types.push_back(curType);
5677       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5678       typeRangeVals.push_back((int)std::distance(connI,i));
5679     }
5680   //
5681   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5682   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5683   MCAuto<DataArrayInt> tmp0=castArr;
5684   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5685   MCAuto<DataArrayInt> tmp2=castsPresent;
5686   //
5687   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5688   code.resize(3*nbOfCastsFinal);
5689   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5690   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5691   for(int i=0;i<nbOfCastsFinal;i++)
5692     {
5693       int castId=castsPresent->getIJ(i,0);
5694       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5695       idsInPflPerType2.push_back(tmp3);
5696       code[3*i]=(int)types[castId];
5697       code[3*i+1]=tmp3->getNumberOfTuples();
5698       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5699       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5700         {
5701           tmp4->copyStringInfoFrom(*profile);
5702           idsPerType2.push_back(tmp4);
5703           code[3*i+2]=(int)idsPerType2.size()-1;
5704         }
5705       else
5706         {
5707           code[3*i+2]=-1;
5708         }
5709     }
5710   std::size_t sz2=idsInPflPerType2.size();
5711   idsInPflPerType.resize(sz2);
5712   for(std::size_t i=0;i<sz2;i++)
5713     {
5714       DataArrayInt *locDa=idsInPflPerType2[i];
5715       locDa->incrRef();
5716       idsInPflPerType[i]=locDa;
5717     }
5718   std::size_t sz=idsPerType2.size();
5719   idsPerType.resize(sz);
5720   for(std::size_t i=0;i<sz;i++)
5721     {
5722       DataArrayInt *locDa=idsPerType2[i];
5723       locDa->incrRef();
5724       idsPerType[i]=locDa;
5725     }
5726 }
5727
5728 /*!
5729  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5730  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5731  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5732  * 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.
5733  */
5734 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5735 {
5736   checkFullyDefined();
5737   nM1LevMesh->checkFullyDefined();
5738   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5740   if(_coords!=nM1LevMesh->getCoords())
5741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5742   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5743   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5744   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5745   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5746   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5747   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5748   tmp->setConnectivity(tmp0,tmp1);
5749   tmp->renumberCells(ret0->begin(),false);
5750   revDesc=tmp->getNodalConnectivity();
5751   revDescIndx=tmp->getNodalConnectivityIndex();
5752   DataArrayInt *ret=0;
5753   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5754     {
5755       int tmp2;
5756       ret->getMaxValue(tmp2);
5757       ret->decrRef();
5758       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5759       throw INTERP_KERNEL::Exception(oss.str());
5760     }
5761   nM1LevMeshIds=ret;
5762   //
5763   revDesc->incrRef();
5764   revDescIndx->incrRef();
5765   ret1->incrRef();
5766   ret0->incrRef();
5767   meshnM1Old2New=ret0;
5768   return ret1;
5769 }
5770
5771 /*!
5772  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5773  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5774  * in "Old to New" mode.
5775  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5776  *          this array using decrRef() as it is no more needed.
5777  *  \throw If the nodal connectivity of cells is not defined.
5778  */
5779 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5780 {
5781   checkConnectivityFullyDefined();
5782   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5783   renumberCells(ret->begin(),false);
5784   return ret.retn();
5785 }
5786
5787 /*!
5788  * This methods checks that cells are sorted by their types.
5789  * This method makes asumption (no check) that connectivity is correctly set before calling.
5790  */
5791 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5792 {
5793   checkFullyDefined();
5794   const int *conn=_nodal_connec->begin();
5795   const int *connI=_nodal_connec_index->begin();
5796   int nbOfCells=getNumberOfCells();
5797   std::set<INTERP_KERNEL::NormalizedCellType> types;
5798   for(const int *i=connI;i!=connI+nbOfCells;)
5799     {
5800       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5801       if(types.find(curType)!=types.end())
5802         return false;
5803       types.insert(curType);
5804       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5805     }
5806   return true;
5807 }
5808
5809 /*!
5810  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5811  * The geometric type order is specified by MED file.
5812  * 
5813  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5814  */
5815 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5816 {
5817   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5818 }
5819
5820 /*!
5821  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5822  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5823  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5824  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5825  */
5826 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5827 {
5828   checkFullyDefined();
5829   const int *conn=_nodal_connec->begin();
5830   const int *connI=_nodal_connec_index->begin();
5831   int nbOfCells=getNumberOfCells();
5832   if(nbOfCells==0)
5833     return true;
5834   int lastPos=-1;
5835   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5836   for(const int *i=connI;i!=connI+nbOfCells;)
5837     {
5838       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5839       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5840       if(isTypeExists!=orderEnd)
5841         {
5842           int pos=(int)std::distance(orderBg,isTypeExists);
5843           if(pos<=lastPos)
5844             return false;
5845           lastPos=pos;
5846           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5847         }
5848       else
5849         {
5850           if(sg.find(curType)==sg.end())
5851             {
5852               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5853               sg.insert(curType);
5854             }
5855           else
5856             return false;
5857         }
5858     }
5859   return true;
5860 }
5861
5862 /*!
5863  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5864  * 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
5865  * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurence of type in 'this'.
5866  */
5867 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
5868 {
5869   checkConnectivityFullyDefined();
5870   int nbOfCells=getNumberOfCells();
5871   const int *conn=_nodal_connec->begin();
5872   const int *connI=_nodal_connec_index->begin();
5873   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
5874   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
5875   tmpa->alloc(nbOfCells,1);
5876   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5877   tmpb->fillWithZero();
5878   int *tmp=tmpa->getPointer();
5879   int *tmp2=tmpb->getPointer();
5880   for(const int *i=connI;i!=connI+nbOfCells;i++)
5881     {
5882       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5883       if(where!=orderEnd)
5884         {
5885           int pos=(int)std::distance(orderBg,where);
5886           tmp2[pos]++;
5887           tmp[std::distance(connI,i)]=pos;
5888         }
5889       else
5890         {
5891           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5892           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5893           oss << " has a type " << cm.getRepr() << " not in input array of type !";
5894           throw INTERP_KERNEL::Exception(oss.str());
5895         }
5896     }
5897   nbPerType=tmpb.retn();
5898   return tmpa.retn();
5899 }
5900
5901 /*!
5902  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
5903  *
5904  * \return a new object containing the old to new correspondance.
5905  *
5906  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5907  */
5908 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
5909 {
5910   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5911 }
5912
5913 /*!
5914  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
5915  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5916  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5917  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5918  */
5919 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5920 {
5921   DataArrayInt *nbPerType=0;
5922   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5923   nbPerType->decrRef();
5924   return tmpa->buildPermArrPerLevel();
5925 }
5926
5927 /*!
5928  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
5929  * The number of cells remains unchanged after the call of this method.
5930  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5931  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5932  *
5933  * \return the array giving the correspondance old to new.
5934  */
5935 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5936 {
5937   checkFullyDefined();
5938   computeTypes();
5939   const int *conn=_nodal_connec->begin();
5940   const int *connI=_nodal_connec_index->begin();
5941   int nbOfCells=getNumberOfCells();
5942   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5943   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5944     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5945       {
5946         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5947         types.push_back(curType);
5948         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5949       }
5950   DataArrayInt *ret=DataArrayInt::New();
5951   ret->alloc(nbOfCells,1);
5952   int *retPtr=ret->getPointer();
5953   std::fill(retPtr,retPtr+nbOfCells,-1);
5954   int newCellId=0;
5955   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5956     {
5957       for(const int *i=connI;i!=connI+nbOfCells;i++)
5958         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5959           retPtr[std::distance(connI,i)]=newCellId++;
5960     }
5961   renumberCells(retPtr,false);
5962   return ret;
5963 }
5964
5965 /*!
5966  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
5967  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5968  * This method makes asumption that connectivity is correctly set before calling.
5969  */
5970 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5971 {
5972   checkConnectivityFullyDefined();
5973   const int *conn=_nodal_connec->begin();
5974   const int *connI=_nodal_connec_index->begin();
5975   int nbOfCells=getNumberOfCells();
5976   std::vector<MEDCouplingUMesh *> ret;
5977   for(const int *i=connI;i!=connI+nbOfCells;)
5978     {
5979       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5980       int beginCellId=(int)std::distance(connI,i);
5981       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5982       int endCellId=(int)std::distance(connI,i);
5983       int sz=endCellId-beginCellId;
5984       int *cells=new int[sz];
5985       for(int j=0;j<sz;j++)
5986         cells[j]=beginCellId+j;
5987       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
5988       delete [] cells;
5989       ret.push_back(m);
5990     }
5991   return ret;
5992 }
5993
5994 /*!
5995  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
5996  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
5997  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
5998  *
5999  * \return a newly allocated instance, that the caller must manage.
6000  * \throw If \a this contains more than one geometric type.
6001  * \throw If the nodal connectivity of \a this is not fully defined.
6002  * \throw If the internal data is not coherent.
6003  */
6004 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6005 {
6006   checkConnectivityFullyDefined();
6007   if(_types.size()!=1)
6008     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6009   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6010   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6011   ret->setCoords(getCoords());
6012   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6013   if(retC)
6014     {
6015       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6016       retC->setNodalConnectivity(c);
6017     }
6018   else
6019     {
6020       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6021       if(!retD)
6022         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6023       DataArrayInt *c=0,*ci=0;
6024       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6025       MCAuto<DataArrayInt> cs(c),cis(ci);
6026       retD->setNodalConnectivity(cs,cis);
6027     }
6028   return ret.retn();
6029 }
6030
6031 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6032 {
6033   checkConnectivityFullyDefined();
6034   if(_types.size()!=1)
6035     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6036   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6037   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6038   if(cm.isDynamic())
6039     {
6040       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6041       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6042       throw INTERP_KERNEL::Exception(oss.str());
6043     }
6044   int nbCells=getNumberOfCells();
6045   int typi=(int)typ;
6046   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6047   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6048   int *outPtr=connOut->getPointer();
6049   const int *conn=_nodal_connec->begin();
6050   const int *connI=_nodal_connec_index->begin();
6051   nbNodesPerCell++;
6052   for(int i=0;i<nbCells;i++,connI++)
6053     {
6054       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6055         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6056       else
6057         {
6058           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 << ") !";
6059           throw INTERP_KERNEL::Exception(oss.str());
6060         }
6061     }
6062   return connOut.retn();
6063 }
6064
6065 /*!
6066  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6067  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6068  * \param nodalConn
6069  * \param nodalConnI
6070  */
6071 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6072 {
6073   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6074   checkConnectivityFullyDefined();
6075   if(_types.size()!=1)
6076     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6077   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6078   if(lgth<nbCells)
6079     throw INTERP_KERNEL::Exception(msg0);
6080   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6081   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6082   int *cp(c->getPointer()),*cip(ci->getPointer());
6083   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6084   cip[0]=0;
6085   for(int i=0;i<nbCells;i++,cip++,incip++)
6086     {
6087       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6088       int delta(stop-strt);
6089       if(delta>=1)
6090         {
6091           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6092             cp=std::copy(incp+strt,incp+stop,cp);
6093           else
6094             throw INTERP_KERNEL::Exception(msg0);
6095         }
6096       else
6097         throw INTERP_KERNEL::Exception(msg0);
6098       cip[1]=cip[0]+delta;
6099     }
6100   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6101 }
6102
6103 /*!
6104  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6105  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6106  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6107  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6108  * are not used here to avoid the build of big permutation array.
6109  *
6110  * \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
6111  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6112  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6113  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6114  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6115  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6116  * \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
6117  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6118  */
6119 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6120                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6121                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6122 {
6123   std::vector<const MEDCouplingUMesh *> ms2;
6124   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6125     if(*it)
6126       {
6127         (*it)->checkConnectivityFullyDefined();
6128         ms2.push_back(*it);
6129       }
6130   if(ms2.empty())
6131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6132   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6133   int meshDim=ms2[0]->getMeshDimension();
6134   std::vector<const MEDCouplingUMesh *> m1ssm;
6135   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6136   //
6137   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6138   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6139   int fake=0,rk=0;
6140   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6141   ret1->alloc(0,1); ret2->alloc(0,1);
6142   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6143     {
6144       if(meshDim!=(*it)->getMeshDimension())
6145         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6146       if(refCoo!=(*it)->getCoords())
6147         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6148       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6149       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6150       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6151       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6152         {
6153           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6154           m1ssmSingleAuto.push_back(singleCell);
6155           m1ssmSingle.push_back(singleCell);
6156           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6157         }
6158     }
6159   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6160   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6161   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6162   for(std::size_t i=0;i<m1ssm.size();i++)
6163     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6164   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6165   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6166   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6167   return ret0.retn();
6168 }
6169
6170 /*!
6171  * This method returns a newly created DataArrayInt instance.
6172  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6173  */
6174 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6175 {
6176   checkFullyDefined();
6177   const int *conn=_nodal_connec->begin();
6178   const int *connIndex=_nodal_connec_index->begin();
6179   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6180   for(const int *w=begin;w!=end;w++)
6181     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6182       ret->pushBackSilent(*w);
6183   return ret.retn();
6184 }
6185
6186 /*!
6187  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6188  * are in [0:getNumberOfCells())
6189  */
6190 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6191 {
6192   checkFullyDefined();
6193   const int *conn=_nodal_connec->begin();
6194   const int *connI=_nodal_connec_index->begin();
6195   int nbOfCells=getNumberOfCells();
6196   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6197   int *tmp=new int[nbOfCells];
6198   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6199     {
6200       int j=0;
6201       for(const int *i=connI;i!=connI+nbOfCells;i++)
6202         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6203           tmp[std::distance(connI,i)]=j++;
6204     }
6205   DataArrayInt *ret=DataArrayInt::New();
6206   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6207   ret->copyStringInfoFrom(*da);
6208   int *retPtr=ret->getPointer();
6209   const int *daPtr=da->begin();
6210   int nbOfElems=da->getNbOfElems();
6211   for(int k=0;k<nbOfElems;k++)
6212     retPtr[k]=tmp[daPtr[k]];
6213   delete [] tmp;
6214   return ret;
6215 }
6216
6217 /*!
6218  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6219  * This method \b works \b for mesh sorted by type.
6220  * cells whose ids is in 'idsPerGeoType' array.
6221  * This method conserves coords and name of mesh.
6222  */
6223 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6224 {
6225   std::vector<int> code=getDistributionOfTypes();
6226   std::size_t nOfTypesInThis=code.size()/3;
6227   int sz=0,szOfType=0;
6228   for(std::size_t i=0;i<nOfTypesInThis;i++)
6229     {
6230       if(code[3*i]!=type)
6231         sz+=code[3*i+1];
6232       else
6233         szOfType=code[3*i+1];
6234     }
6235   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6236     if(*work<0 || *work>=szOfType)
6237       {
6238         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6239         oss << ". It should be in [0," << szOfType << ") !";
6240         throw INTERP_KERNEL::Exception(oss.str());
6241       }
6242   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6243   int *idsPtr=idsTokeep->getPointer();
6244   int offset=0;
6245   for(std::size_t i=0;i<nOfTypesInThis;i++)
6246     {
6247       if(code[3*i]!=type)
6248         for(int j=0;j<code[3*i+1];j++)
6249           *idsPtr++=offset+j;
6250       else
6251         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6252       offset+=code[3*i+1];
6253     }
6254   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6255   ret->copyTinyInfoFrom(this);
6256   return ret.retn();
6257 }
6258
6259 /*!
6260  * This method returns a vector of size 'this->getNumberOfCells()'.
6261  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6262  */
6263 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6264 {
6265   int ncell=getNumberOfCells();
6266   std::vector<bool> ret(ncell);
6267   const int *cI=getNodalConnectivityIndex()->begin();
6268   const int *c=getNodalConnectivity()->begin();
6269   for(int i=0;i<ncell;i++)
6270     {
6271       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6272       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6273       ret[i]=cm.isQuadratic();
6274     }
6275   return ret;
6276 }
6277
6278 /*!
6279  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6280  */
6281 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6282 {
6283   if(other->getType()!=UNSTRUCTURED)
6284     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6285   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6286   return MergeUMeshes(this,otherC);
6287 }
6288
6289 /*!
6290  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6291  * computed by averaging coordinates of cell nodes, so this method is not a right
6292  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6293  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6294  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6295  *          components. The caller is to delete this array using decrRef() as it is
6296  *          no more needed.
6297  *  \throw If the coordinates array is not set.
6298  *  \throw If the nodal connectivity of cells is not defined.
6299  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6300  */
6301 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6302 {
6303   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6304   int spaceDim=getSpaceDimension();
6305   int nbOfCells=getNumberOfCells();
6306   ret->alloc(nbOfCells,spaceDim);
6307   ret->copyStringInfoFrom(*getCoords());
6308   double *ptToFill=ret->getPointer();
6309   const int *nodal=_nodal_connec->begin();
6310   const int *nodalI=_nodal_connec_index->begin();
6311   const double *coor=_coords->begin();
6312   for(int i=0;i<nbOfCells;i++)
6313     {
6314       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6315       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6316       ptToFill+=spaceDim;
6317     }
6318   return ret.retn();
6319 }
6320
6321 /*!
6322  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6323  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6324  * 
6325  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6326  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6327  * 
6328  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6329  * \throw If \a this is not fully defined (coordinates and connectivity)
6330  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6331  */
6332 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6333 {
6334   checkFullyDefined();
6335   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6336   int spaceDim=getSpaceDimension();
6337   int nbOfCells=getNumberOfCells();
6338   int nbOfNodes=getNumberOfNodes();
6339   ret->alloc(nbOfCells,spaceDim);
6340   double *ptToFill=ret->getPointer();
6341   const int *nodal=_nodal_connec->begin();
6342   const int *nodalI=_nodal_connec_index->begin();
6343   const double *coor=_coords->begin();
6344   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6345     {
6346       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6347       std::fill(ptToFill,ptToFill+spaceDim,0.);
6348       if(type!=INTERP_KERNEL::NORM_POLYHED)
6349         {
6350           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6351             {
6352               if(*conn>=0 && *conn<nbOfNodes)
6353                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6354               else
6355                 {
6356                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6357                   throw INTERP_KERNEL::Exception(oss.str());
6358                 }
6359             }
6360           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6361           if(nbOfNodesInCell>0)
6362             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6363           else
6364             {
6365               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6366               throw INTERP_KERNEL::Exception(oss.str());
6367             }
6368         }
6369       else
6370         {
6371           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6372           s.erase(-1);
6373           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6374             {
6375               if(*it>=0 && *it<nbOfNodes)
6376                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6377               else
6378                 {
6379                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6380                   throw INTERP_KERNEL::Exception(oss.str());
6381                 }
6382             }
6383           if(!s.empty())
6384             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6385           else
6386             {
6387               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6388               throw INTERP_KERNEL::Exception(oss.str());
6389             }
6390         }
6391     }
6392   return ret.retn();
6393 }
6394
6395 /*!
6396  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6397  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6398  * are specified via an array of cell ids. 
6399  *  \warning Validity of the specified cell ids is not checked! 
6400  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6401  *  \param [in] begin - an array of cell ids of interest.
6402  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6403  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6404  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6405  *          caller is to delete this array using decrRef() as it is no more needed. 
6406  *  \throw If the coordinates array is not set.
6407  *  \throw If the nodal connectivity of cells is not defined.
6408  *
6409  *  \if ENABLE_EXAMPLES
6410  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6411  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6412  *  \endif
6413  */
6414 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6415 {
6416   DataArrayDouble *ret=DataArrayDouble::New();
6417   int spaceDim=getSpaceDimension();
6418   int nbOfTuple=(int)std::distance(begin,end);
6419   ret->alloc(nbOfTuple,spaceDim);
6420   double *ptToFill=ret->getPointer();
6421   double *tmp=new double[spaceDim];
6422   const int *nodal=_nodal_connec->begin();
6423   const int *nodalI=_nodal_connec_index->begin();
6424   const double *coor=_coords->begin();
6425   for(const int *w=begin;w!=end;w++)
6426     {
6427       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6428       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6429       ptToFill+=spaceDim;
6430     }
6431   delete [] tmp;
6432   return ret;
6433 }
6434
6435 /*!
6436  * 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".
6437  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6438  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6439  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6440  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6441  * 
6442  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6443  * \throw If spaceDim!=3 or meshDim!=2.
6444  * \throw If connectivity of \a this is invalid.
6445  * \throw If connectivity of a cell in \a this points to an invalid node.
6446  */
6447 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6448 {
6449   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6450   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6451   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6453   ret->alloc(nbOfCells,4);
6454   double *retPtr(ret->getPointer());
6455   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6456   const double *coor(_coords->begin());
6457   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6458     {
6459       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6460       if(nodalI[1]-nodalI[0]>=3)
6461         {
6462           for(int j=0;j<3;j++)
6463             {
6464               int nodeId(nodal[nodalI[0]+1+j]);
6465               if(nodeId>=0 && nodeId<nbOfNodes)
6466                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6467               else
6468                 {
6469                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6470                   throw INTERP_KERNEL::Exception(oss.str());
6471                 }
6472             }
6473         }
6474       else
6475         {
6476           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6477           throw INTERP_KERNEL::Exception(oss.str());
6478         }
6479       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6480       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6481     }
6482   return ret.retn();
6483 }
6484
6485 /*!
6486  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6487  * 
6488  */
6489 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6490 {
6491   if(!da)
6492     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6493   da->checkAllocated();
6494   std::string name(da->getName());
6495   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6496   if(name.empty())
6497     ret->setName("Mesh");
6498   ret->setCoords(da);
6499   int nbOfTuples(da->getNumberOfTuples());
6500   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6501   c->alloc(2*nbOfTuples,1);
6502   cI->alloc(nbOfTuples+1,1);
6503   int *cp(c->getPointer()),*cip(cI->getPointer());
6504   *cip++=0;
6505   for(int i=0;i<nbOfTuples;i++)
6506     {
6507       *cp++=INTERP_KERNEL::NORM_POINT1;
6508       *cp++=i;
6509       *cip++=2*(i+1);
6510     }
6511   ret->setConnectivity(c,cI,true);
6512   return ret.retn();
6513 }
6514
6515 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6516 {
6517   if(!da)
6518     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6519   da->checkAllocated();
6520   std::string name(da->getName());
6521   MCAuto<MEDCouplingUMesh> ret;
6522   {
6523     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6524     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6525     arr->alloc(da->getNumberOfTuples());
6526     tmp->setCoordsAt(0,arr);
6527     ret=tmp->buildUnstructured();
6528   }
6529   ret->setCoords(da);
6530   if(name.empty())
6531     ret->setName("Mesh");
6532   else
6533     ret->setName(name);
6534   return ret;
6535 }
6536
6537 /*!
6538  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6539  * Cells and nodes of
6540  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6541  *  \param [in] mesh1 - the first mesh.
6542  *  \param [in] mesh2 - the second mesh.
6543  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6544  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6545  *          is no more needed.
6546  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6547  *  \throw If the coordinates array is not set in none of the meshes.
6548  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6549  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6550  */
6551 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6552 {
6553   std::vector<const MEDCouplingUMesh *> tmp(2);
6554   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6555   return MergeUMeshes(tmp);
6556 }
6557
6558 /*!
6559  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6560  * Cells and nodes of
6561  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6562  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6563  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6564  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6565  *          is no more needed.
6566  *  \throw If \a a.size() == 0.
6567  *  \throw If \a a[ *i* ] == NULL.
6568  *  \throw If the coordinates array is not set in none of the meshes.
6569  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6570  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6571  */
6572 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6573 {
6574   std::size_t sz=a.size();
6575   if(sz==0)
6576     return MergeUMeshesLL(a);
6577   for(std::size_t ii=0;ii<sz;ii++)
6578     if(!a[ii])
6579       {
6580         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6581         throw INTERP_KERNEL::Exception(oss.str());
6582       }
6583   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6584   std::vector< const MEDCouplingUMesh * > aa(sz);
6585   int spaceDim=-3;
6586   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6587     {
6588       const MEDCouplingUMesh *cur=a[i];
6589       const DataArrayDouble *coo=cur->getCoords();
6590       if(coo)
6591         spaceDim=coo->getNumberOfComponents();
6592     }
6593   if(spaceDim==-3)
6594     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6595   for(std::size_t i=0;i<sz;i++)
6596     {
6597       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6598       aa[i]=bb[i];
6599     }
6600   return MergeUMeshesLL(aa);
6601 }
6602
6603 /*!
6604  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6605  * dimension and sharing the node coordinates array.
6606  * All cells of the first mesh precede all cells of the second mesh
6607  * within the result mesh.
6608  *  \param [in] mesh1 - the first mesh.
6609  *  \param [in] mesh2 - the second mesh.
6610  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6611  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6612  *          is no more needed.
6613  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6614  *  \throw If the meshes do not share the node coordinates array.
6615  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6616  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6617  */
6618 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6619 {
6620   std::vector<const MEDCouplingUMesh *> tmp(2);
6621   tmp[0]=mesh1; tmp[1]=mesh2;
6622   return MergeUMeshesOnSameCoords(tmp);
6623 }
6624
6625 /*!
6626  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6627  * dimension and sharing the node coordinates array.
6628  * All cells of the *i*-th mesh precede all cells of the
6629  * (*i*+1)-th mesh within the result mesh.
6630  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6631  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6632  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6633  *          is no more needed.
6634  *  \throw If \a a.size() == 0.
6635  *  \throw If \a a[ *i* ] == NULL.
6636  *  \throw If the meshes do not share the node coordinates array.
6637  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6638  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6639  */
6640 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6641 {
6642   if(meshes.empty())
6643     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6644   for(std::size_t ii=0;ii<meshes.size();ii++)
6645     if(!meshes[ii])
6646       {
6647         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6648         throw INTERP_KERNEL::Exception(oss.str());
6649       }
6650   const DataArrayDouble *coords=meshes.front()->getCoords();
6651   int meshDim=meshes.front()->getMeshDimension();
6652   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6653   int meshLgth=0;
6654   int meshIndexLgth=0;
6655   for(;iter!=meshes.end();iter++)
6656     {
6657       if(coords!=(*iter)->getCoords())
6658         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6659       if(meshDim!=(*iter)->getMeshDimension())
6660         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6661       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6662       meshIndexLgth+=(*iter)->getNumberOfCells();
6663     }
6664   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6665   nodal->alloc(meshLgth,1);
6666   int *nodalPtr=nodal->getPointer();
6667   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6668   nodalIndex->alloc(meshIndexLgth+1,1);
6669   int *nodalIndexPtr=nodalIndex->getPointer();
6670   int offset=0;
6671   for(iter=meshes.begin();iter!=meshes.end();iter++)
6672     {
6673       const int *nod=(*iter)->getNodalConnectivity()->begin();
6674       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6675       int nbOfCells=(*iter)->getNumberOfCells();
6676       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6677       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6678       if(iter!=meshes.begin())
6679         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6680       else
6681         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6682       offset+=meshLgth2;
6683     }
6684   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6685   ret->setName("merge");
6686   ret->setMeshDimension(meshDim);
6687   ret->setConnectivity(nodal,nodalIndex,true);
6688   ret->setCoords(coords);
6689   return ret;
6690 }
6691
6692 /*!
6693  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6694  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6695  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6696  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6697  * New" mode are returned for each input mesh.
6698  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6699  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6700  *          valid values [0,1,2], see zipConnectivityTraducer().
6701  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6702  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6703  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6704  *          no more needed.
6705  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6706  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6707  *          is no more needed.
6708  *  \throw If \a meshes.size() == 0.
6709  *  \throw If \a meshes[ *i* ] == NULL.
6710  *  \throw If the meshes do not share the node coordinates array.
6711  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6712  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6713  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6714  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6715  */
6716 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6717 {
6718   //All checks are delegated to MergeUMeshesOnSameCoords
6719   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6720   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6721   corr.resize(meshes.size());
6722   std::size_t nbOfMeshes=meshes.size();
6723   int offset=0;
6724   const int *o2nPtr=o2n->begin();
6725   for(std::size_t i=0;i<nbOfMeshes;i++)
6726     {
6727       DataArrayInt *tmp=DataArrayInt::New();
6728       int curNbOfCells=meshes[i]->getNumberOfCells();
6729       tmp->alloc(curNbOfCells,1);
6730       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6731       offset+=curNbOfCells;
6732       tmp->setName(meshes[i]->getName());
6733       corr[i]=tmp;
6734     }
6735   return ret.retn();
6736 }
6737
6738 /*!
6739  * Makes all given meshes share the nodal connectivity array. The common connectivity
6740  * array is created by concatenating the connectivity arrays of all given meshes. All
6741  * the given meshes must be of the same space dimension but dimension of cells **can
6742  * differ**. This method is particulary useful in MEDLoader context to build a \ref
6743  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6744  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6745  *  \param [in,out] meshes - a vector of meshes to update.
6746  *  \throw If any of \a meshes is NULL.
6747  *  \throw If the coordinates array is not set in any of \a meshes.
6748  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6749  *  \throw If \a meshes are of different space dimension.
6750  */
6751 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6752 {
6753   std::size_t sz=meshes.size();
6754   if(sz==0 || sz==1)
6755     return;
6756   std::vector< const DataArrayDouble * > coords(meshes.size());
6757   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6758   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6759     {
6760       if((*it))
6761         {
6762           (*it)->checkConnectivityFullyDefined();
6763           const DataArrayDouble *coo=(*it)->getCoords();
6764           if(coo)
6765             *it2=coo;
6766           else
6767             {
6768               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6769               oss << " has no coordinate array defined !";
6770               throw INTERP_KERNEL::Exception(oss.str());
6771             }
6772         }
6773       else
6774         {
6775           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6776           oss << " is null !";
6777           throw INTERP_KERNEL::Exception(oss.str());
6778         }
6779     }
6780   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6781   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6782   int offset=(*it)->getNumberOfNodes();
6783   (*it++)->setCoords(res);
6784   for(;it!=meshes.end();it++)
6785     {
6786       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6787       (*it)->setCoords(res);
6788       (*it)->shiftNodeNumbersInConn(offset);
6789       offset+=oldNumberOfNodes;
6790     }
6791 }
6792
6793 /*!
6794  * Merges nodes coincident with a given precision within all given meshes that share
6795  * the nodal connectivity array. The given meshes **can be of different** mesh
6796  * dimension. This method is particulary useful in MEDLoader context to build a \ref
6797  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6798  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6799  *  \param [in,out] meshes - a vector of meshes to update.
6800  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6801  *  \throw If any of \a meshes is NULL.
6802  *  \throw If the \a meshes do not share the same node coordinates array.
6803  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6804  */
6805 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6806 {
6807   if(meshes.empty())
6808     return ;
6809   std::set<const DataArrayDouble *> s;
6810   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6811     {
6812       if(*it)
6813         s.insert((*it)->getCoords());
6814       else
6815         {
6816           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 !";
6817           throw INTERP_KERNEL::Exception(oss.str());
6818         }
6819     }
6820   if(s.size()!=1)
6821     {
6822       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 !";
6823       throw INTERP_KERNEL::Exception(oss.str());
6824     }
6825   const DataArrayDouble *coo=*(s.begin());
6826   if(!coo)
6827     return;
6828   //
6829   DataArrayInt *comm,*commI;
6830   coo->findCommonTuples(eps,-1,comm,commI);
6831   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6832   int oldNbOfNodes=coo->getNumberOfTuples();
6833   int newNbOfNodes;
6834   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6835   if(oldNbOfNodes==newNbOfNodes)
6836     return ;
6837   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6838   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6839     {
6840       (*it)->renumberNodesInConn(o2n->begin());
6841       (*it)->setCoords(newCoords);
6842     } 
6843 }
6844
6845
6846 /*!
6847  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
6848  */
6849 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6850 {
6851   std::size_t i, ip1;
6852   double v[3]={0.,0.,0.};
6853   std::size_t sz=std::distance(begin,end);
6854   if(isQuadratic)
6855     sz/=2;
6856   for(i=0;i<sz;i++)
6857     {
6858       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];
6859       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6860       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6861     }
6862   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6863
6864   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
6865   // SEG3 forming a circle):
6866   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
6867     {
6868       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
6869       for(std::size_t j=0;j<sz;j++)
6870         {
6871           if (j%2)  // current point i is quadratic, next point i+1 is standard
6872             {
6873               i = sz+j;
6874               ip1 = (j+1)%sz; // ip1 = "i+1"
6875             }
6876           else      // current point i is standard, next point i+1 is quadratic
6877             {
6878               i = j;
6879               ip1 = j+sz;
6880             }
6881           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
6882           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
6883           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
6884         }
6885       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6886     }
6887   return (ret>0.);
6888 }
6889
6890 /*!
6891  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
6892  */
6893 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6894 {
6895   std::vector<std::pair<int,int> > edges;
6896   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6897   const int *bgFace=begin;
6898   for(std::size_t i=0;i<nbOfFaces;i++)
6899     {
6900       const int *endFace=std::find(bgFace+1,end,-1);
6901       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6902       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6903         {
6904           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6905           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6906             return false;
6907           edges.push_back(p1);
6908         }
6909       bgFace=endFace+1;
6910     }
6911   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6912 }
6913
6914 /*!
6915  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
6916  */
6917 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6918 {
6919   double vec0[3],vec1[3];
6920   std::size_t sz=std::distance(begin,end);
6921   if(sz%2!=0)
6922     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6923   int nbOfNodes=(int)sz/2;
6924   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6925   const double *pt0=coords+3*begin[0];
6926   const double *pt1=coords+3*begin[nbOfNodes];
6927   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6928   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6929 }
6930
6931 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6932 {
6933   std::size_t sz=std::distance(begin,end);
6934   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6935   std::size_t nbOfNodes(sz/2);
6936   std::copy(begin,end,(int *)tmp);
6937   for(std::size_t j=1;j<nbOfNodes;j++)
6938     {
6939       begin[j]=tmp[nbOfNodes-j];
6940       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6941     }
6942 }
6943
6944 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6945 {
6946   std::size_t sz=std::distance(begin,end);
6947   if(sz!=4)
6948     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
6949   double vec0[3],vec1[3];
6950   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6951   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]; 
6952   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;
6953 }
6954
6955 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
6956 {
6957   std::size_t sz=std::distance(begin,end);
6958   if(sz!=5)
6959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
6960   double vec0[3];
6961   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
6962   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
6963   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
6964 }
6965
6966 /*!
6967  * 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 ) 
6968  * 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
6969  * a 2D space.
6970  *
6971  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6972  * \param [in] coords the coordinates with nb of components exactly equal to 3
6973  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6974  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6975  * \param [out] res the result is put at the end of the vector without any alteration of the data.
6976  */
6977 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
6978 {
6979   int nbFaces=std::count(begin+1,end,-1)+1;
6980   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6981   double *vPtr=v->getPointer();
6982   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6983   double *pPtr=p->getPointer();
6984   const int *stFaceConn=begin+1;
6985   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6986     {
6987       const int *endFaceConn=std::find(stFaceConn,end,-1);
6988       ComputeVecAndPtOfFace(eps,coords->begin(),stFaceConn,endFaceConn,vPtr,pPtr);
6989       stFaceConn=endFaceConn+1;
6990     }
6991   pPtr=p->getPointer(); vPtr=v->getPointer();
6992   DataArrayInt *comm1=0,*commI1=0;
6993   v->findCommonTuples(eps,-1,comm1,commI1);
6994   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6995   const int *comm1Ptr=comm1->begin();
6996   const int *commI1Ptr=commI1->begin();
6997   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6998   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
6999   //
7000   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7001   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7002   mm->finishInsertingCells();
7003   //
7004   for(int i=0;i<nbOfGrps1;i++)
7005     {
7006       int vecId=comm1Ptr[commI1Ptr[i]];
7007       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7008       DataArrayInt *comm2=0,*commI2=0;
7009       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7010       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7011       const int *comm2Ptr=comm2->begin();
7012       const int *commI2Ptr=commI2->begin();
7013       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7014       for(int j=0;j<nbOfGrps2;j++)
7015         {
7016           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7017             {
7018               res->insertAtTheEnd(begin,end);
7019               res->pushBackSilent(-1);
7020             }
7021           else
7022             {
7023               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7024               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7025               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7026               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7027               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7028               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7029               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7030               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7031               const int *idsNodePtr=idsNode->begin();
7032               double center[3]; center[0]=pPtr[pointId]*vPtr[3*vecId]; center[1]=pPtr[pointId]*vPtr[3*vecId+1]; center[2]=pPtr[pointId]*vPtr[3*vecId+2];
7033               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7034               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7035               if(std::abs(norm)>eps)
7036                 {
7037                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7038                   mm3->rotate(center,vec,angle);
7039                 }
7040               mm3->changeSpaceDimension(2);
7041               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7042               const int *conn4=mm4->getNodalConnectivity()->begin();
7043               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7044               int nbOfCells=mm4->getNumberOfCells();
7045               for(int k=0;k<nbOfCells;k++)
7046                 {
7047                   int l=0;
7048                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7049                     res->pushBackSilent(idsNodePtr[*work]);
7050                   res->pushBackSilent(-1);
7051                 }
7052             }
7053         }
7054     }
7055   res->popBackSilent();
7056 }
7057
7058 /*!
7059  * 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
7060  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7061  * 
7062  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7063  * \param [in] coords coordinates expected to have 3 components.
7064  * \param [in] begin start of the nodal connectivity of the face.
7065  * \param [in] end end of the nodal connectivity (excluded) of the face.
7066  * \param [out] v the normalized vector of size 3
7067  * \param [out] p the pos of plane
7068  */
7069 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7070 {
7071   std::size_t nbPoints=std::distance(begin,end);
7072   if(nbPoints<3)
7073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7074   double vec[3]={0.,0.,0.};
7075   std::size_t j=0;
7076   bool refFound=false;
7077   for(;j<nbPoints-1 && !refFound;j++)
7078     {
7079       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7080       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7081       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7082       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7083       if(norm>eps)
7084         {
7085           refFound=true;
7086           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7087         }
7088     }
7089   for(std::size_t i=j;i<nbPoints-1;i++)
7090     {
7091       double curVec[3];
7092       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7093       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7094       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7095       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7096       if(norm<eps)
7097         continue;
7098       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7099       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];
7100       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7101       if(norm>eps)
7102         {
7103           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7104           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7105           return ;
7106         }
7107     }
7108   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7109 }
7110
7111 /*!
7112  * This method tries to obtain a well oriented polyhedron.
7113  * If the algorithm fails, an exception will be thrown.
7114  */
7115 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7116 {
7117   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7118   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7119   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7120   isPerm[0]=true;
7121   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7122   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7123   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7124   //
7125   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7126     {
7127       bgFace=begin;
7128       std::size_t smthChanged=0;
7129       for(std::size_t i=0;i<nbOfFaces;i++)
7130         {
7131           endFace=std::find(bgFace+1,end,-1);
7132           nbOfEdgesInFace=std::distance(bgFace,endFace);
7133           if(!isPerm[i])
7134             {
7135               bool b;
7136               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7137                 {
7138                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7139                   std::pair<int,int> p2(p1.second,p1.first);
7140                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7141                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7142                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7143                 }
7144               if(isPerm[i])
7145                 { 
7146                   if(!b)
7147                     std::reverse(bgFace+1,endFace);
7148                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7149                     {
7150                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7151                       std::pair<int,int> p2(p1.second,p1.first);
7152                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7153                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7154                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7155                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7156                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7157                       if(it!=edgesOK.end())
7158                         {
7159                           edgesOK.erase(it);
7160                           edgesFinished.push_back(p1);
7161                         }
7162                       else
7163                         edgesOK.push_back(p1);
7164                     }
7165                 }
7166             }
7167           bgFace=endFace+1;
7168         }
7169       if(smthChanged==0)
7170         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7171     }
7172   if(!edgesOK.empty())
7173     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7174   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7175     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7176       bgFace=begin;
7177       for(std::size_t i=0;i<nbOfFaces;i++)
7178         {
7179           endFace=std::find(bgFace+1,end,-1);
7180           std::reverse(bgFace+1,endFace);
7181           bgFace=endFace+1;
7182         }
7183     }
7184 }
7185
7186
7187 /*!
7188  * This method makes the assumption spacedimension == meshdimension == 2.
7189  * This method works only for linear cells.
7190  * 
7191  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7192  */
7193 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7194 {
7195   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7196     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7197   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7198   int oldNbOfNodes(skin->getNumberOfNodes());
7199   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7200   int nbOfNodesExpected(skin->getNumberOfNodes());
7201   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7202   int nbCells(skin->getNumberOfCells());
7203   if(nbCells==nbOfNodesExpected)
7204     return buildUnionOf2DMeshLinear(skin,n2o);
7205   else if(2*nbCells==nbOfNodesExpected)
7206     return buildUnionOf2DMeshQuadratic(skin,n2o);
7207   else
7208     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7209 }
7210
7211 /*!
7212  * This method makes the assumption spacedimension == meshdimension == 3.
7213  * This method works only for linear cells.
7214  * 
7215  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7216  */
7217 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7218 {
7219   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7220     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7221   MCAuto<MEDCouplingUMesh> m=computeSkin();
7222   const int *conn=m->getNodalConnectivity()->begin();
7223   const int *connI=m->getNodalConnectivityIndex()->begin();
7224   int nbOfCells=m->getNumberOfCells();
7225   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7226   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7227   if(nbOfCells<1)
7228     return ret.retn();
7229   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7230   for(int i=1;i<nbOfCells;i++)
7231     {
7232       *work++=-1;
7233       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7234     }
7235   return ret.retn();
7236 }
7237
7238 /*!
7239  * \brief Creates a graph of cell neighbors
7240  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7241  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7242  *  For example
7243  *  - index:  0 3 5 6 6
7244  *  - value:  1 2 3 2 3 3
7245  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7246  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7247  */
7248 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7249 {
7250   checkConnectivityFullyDefined();
7251
7252   int meshDim = this->getMeshDimension();
7253   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7254   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7255   this->getReverseNodalConnectivity(revConn,indexr);
7256   const int* indexr_ptr=indexr->begin();
7257   const int* revConn_ptr=revConn->begin();
7258
7259   const MEDCoupling::DataArrayInt* index;
7260   const MEDCoupling::DataArrayInt* conn;
7261   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7262   index=this->getNodalConnectivityIndex();
7263   int nbCells=this->getNumberOfCells();
7264   const int* index_ptr=index->begin();
7265   const int* conn_ptr=conn->begin();
7266
7267   //creating graph arcs (cell to cell relations)
7268   //arcs are stored in terms of (index,value) notation
7269   // 0 3 5 6 6
7270   // 1 2 3 2 3 3
7271   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7272   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7273
7274   //warning here one node have less than or equal effective number of cell with it
7275   //but cell could have more than effective nodes
7276   //because other equals nodes in other domain (with other global inode)
7277   std::vector <int> cell2cell_index(nbCells+1,0);
7278   std::vector <int> cell2cell;
7279   cell2cell.reserve(3*nbCells);
7280
7281   for (int icell=0; icell<nbCells;icell++)
7282     {
7283       std::map<int,int > counter;
7284       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7285         {
7286           int inode=conn_ptr[iconn];
7287           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7288             {
7289               int icell2=revConn_ptr[iconnr];
7290               std::map<int,int>::iterator iter=counter.find(icell2);
7291               if (iter!=counter.end()) (iter->second)++;
7292               else counter.insert(std::make_pair(icell2,1));
7293             }
7294         }
7295       for (std::map<int,int>::const_iterator iter=counter.begin();
7296            iter!=counter.end(); iter++)
7297         if (iter->second >= meshDim)
7298           {
7299             cell2cell_index[icell+1]++;
7300             cell2cell.push_back(iter->first);
7301           }
7302     }
7303   indexr->decrRef();
7304   revConn->decrRef();
7305   cell2cell_index[0]=0;
7306   for (int icell=0; icell<nbCells;icell++)
7307     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7308
7309   //filling up index and value to create skylinearray structure
7310   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7311   return array;
7312 }
7313
7314
7315 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7316 {
7317   int nbOfCells=getNumberOfCells();
7318   if(nbOfCells<=0)
7319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7320   ofs << "  <" << getVTKDataSetType() << ">\n";
7321   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7322   ofs << "      <PointData>\n" << pointData << std::endl;
7323   ofs << "      </PointData>\n";
7324   ofs << "      <CellData>\n" << cellData << std::endl;
7325   ofs << "      </CellData>\n";
7326   ofs << "      <Points>\n";
7327   if(getSpaceDimension()==3)
7328     _coords->writeVTK(ofs,8,"Points",byteData);
7329   else
7330     {
7331       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7332       coo->writeVTK(ofs,8,"Points",byteData);
7333     }
7334   ofs << "      </Points>\n";
7335   ofs << "      <Cells>\n";
7336   const int *cPtr=_nodal_connec->begin();
7337   const int *cIPtr=_nodal_connec_index->begin();
7338   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7339   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7340   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7341   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7342   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7343   int szFaceOffsets=0,szConn=0;
7344   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7345     {
7346       *w2=cPtr[cIPtr[i]];
7347       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7348         {
7349           *w1=-1;
7350           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7351           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7352         }
7353       else
7354         {
7355           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7356           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7357           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7358           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7359           w4=std::copy(c.begin(),c.end(),w4);
7360         }
7361     }
7362   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7363   types->writeVTK(ofs,8,"UInt8","types",byteData);
7364   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7365   if(szFaceOffsets!=0)
7366     {//presence of Polyhedra
7367       connectivity->reAlloc(szConn);
7368       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7369       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7370       w1=faces->getPointer();
7371       for(int i=0;i<nbOfCells;i++)
7372         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7373           {
7374             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7375             *w1++=nbFaces;
7376             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7377             for(int j=0;j<nbFaces;j++)
7378               {
7379                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7380                 *w1++=(int)std::distance(w6,w5);
7381                 w1=std::copy(w6,w5,w1);
7382                 w6=w5+1;
7383               }
7384           }
7385       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7386     }
7387   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7388   ofs << "      </Cells>\n";
7389   ofs << "    </Piece>\n";
7390   ofs << "  </" << getVTKDataSetType() << ">\n";
7391 }
7392
7393 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7394 {
7395   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7396   if(_mesh_dim==-2)
7397     { stream << " Not set !"; return ; }
7398   stream << " Mesh dimension : " << _mesh_dim << ".";
7399   if(_mesh_dim==-1)
7400     return ;
7401   if(!_coords)
7402     { stream << " No coordinates set !"; return ; }
7403   if(!_coords->isAllocated())
7404     { stream << " Coordinates set but not allocated !"; return ; }
7405   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7406   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7407   if(!_nodal_connec_index)
7408     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7409   if(!_nodal_connec_index->isAllocated())
7410     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7411   int lgth=_nodal_connec_index->getNumberOfTuples();
7412   int cpt=_nodal_connec_index->getNumberOfComponents();
7413   if(cpt!=1 || lgth<1)
7414     return ;
7415   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7416 }
7417
7418 std::string MEDCouplingUMesh::getVTKDataSetType() const
7419 {
7420   return std::string("UnstructuredGrid");
7421 }
7422
7423 std::string MEDCouplingUMesh::getVTKFileExtension() const
7424 {
7425   return std::string("vtu");
7426 }
7427
7428
7429
7430 /**
7431  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7432  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7433  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7434  * The caller is to deal with the resulting DataArrayInt.
7435  *  \throw If the coordinate array is not set.
7436  *  \throw If the nodal connectivity of the cells is not defined.
7437  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7438  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7439  *
7440  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7441  */
7442 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7443 {
7444   checkFullyDefined();
7445   if(getMeshDimension()!=1)
7446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7447
7448   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7449   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7450   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7451   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7452   const int *d(_d->begin()), *dI(_dI->begin());
7453   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7454   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7455   const int * dsi(_dsi->begin());
7456   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7457   m_points=0;
7458   if (dsii->getNumberOfTuples())
7459     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7460
7461   int nc(getNumberOfCells());
7462   MCAuto<DataArrayInt> result(DataArrayInt::New());
7463   result->alloc(nc,1);
7464
7465   // set of edges not used so far
7466   std::set<int> edgeSet;
7467   for (int i=0; i<nc; edgeSet.insert(i), i++);
7468
7469   int startSeg=0;
7470   int newIdx=0;
7471   // while we have points with only one neighbor segments
7472   do
7473     {
7474       std::list<int> linePiece;
7475       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7476       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7477         {
7478           // Fill the list forward (resp. backward) from the start segment:
7479           int activeSeg = startSeg;
7480           int prevPointId = -20;
7481           int ptId;
7482           while (!edgeSet.empty())
7483             {
7484               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7485                 {
7486                   if (direction==0)
7487                     linePiece.push_back(activeSeg);
7488                   else
7489                     linePiece.push_front(activeSeg);
7490                   edgeSet.erase(activeSeg);
7491                 }
7492
7493               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7494               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7495               if (dsi[ptId] == 1) // hitting the end of the line
7496                 break;
7497               prevPointId = ptId;
7498               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7499               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7500             }
7501         }
7502       // Done, save final piece into DA:
7503       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7504       newIdx += linePiece.size();
7505
7506       // identify next valid start segment (one which is not consumed)
7507       if(!edgeSet.empty())
7508         startSeg = *(edgeSet.begin());
7509     }
7510   while (!edgeSet.empty());
7511   return result.retn();
7512 }
7513
7514 /**
7515  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7516  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7517  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7518  * a minimal creation of new nodes is wanted.
7519  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7520  * nodes if a SEG3 is split without information of middle.
7521  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7522  * avoid to have a non conform mesh.
7523  *
7524  * \return int - the number of new nodes created (in most of cases 0).
7525  * 
7526  * \throw If \a this is not coherent.
7527  * \throw If \a this has not spaceDim equal to 2.
7528  * \throw If \a this has not meshDim equal to 2.
7529  * \throw If some subcells needed to be split are orphan.
7530  * \sa MEDCouplingUMesh::conformize2D
7531  */
7532 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7533 {
7534   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7536   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7537   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7539   if(midOpt==0 && midOptI==0)
7540     {
7541       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7542       return 0;
7543     }
7544   else if(midOpt!=0 && midOptI!=0)
7545     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7546   else
7547     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7548 }
7549
7550 /*!
7551  * 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
7552  * 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
7553  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7554  * 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
7555  * 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.
7556  * 
7557  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7558  */
7559 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7560 {
7561   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7562   if(sz>=4)
7563     {
7564       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7565       if(cm.getDimension()==2)
7566         {
7567           const int *node=nodalConnBg+1;
7568           int startNode=*node++;
7569           double refX=coords[2*startNode];
7570           for(;node!=nodalConnEnd;node++)
7571             {
7572               if(coords[2*(*node)]<refX)
7573                 {
7574                   startNode=*node;
7575                   refX=coords[2*startNode];
7576                 }
7577             }
7578           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7579           refX=1e300;
7580           double tmp1;
7581           double tmp2[2];
7582           double angle0=-M_PI/2;
7583           //
7584           int nextNode=-1;
7585           int prevNode=-1;
7586           double resRef;
7587           double angleNext=0.;
7588           while(nextNode!=startNode)
7589             {
7590               nextNode=-1;
7591               resRef=1e300;
7592               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7593                 {
7594                   if(*node!=tmpOut.back() && *node!=prevNode)
7595                     {
7596                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7597                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7598                       double res;
7599                       if(angleM<=angle0)
7600                         res=angle0-angleM;
7601                       else
7602                         res=angle0-angleM+2.*M_PI;
7603                       if(res<resRef)
7604                         {
7605                           nextNode=*node;
7606                           resRef=res;
7607                           angleNext=angleM;
7608                         }
7609                     }
7610                 }
7611               if(nextNode!=startNode)
7612                 {
7613                   angle0=angleNext-M_PI;
7614                   if(angle0<-M_PI)
7615                     angle0+=2*M_PI;
7616                   prevNode=tmpOut.back();
7617                   tmpOut.push_back(nextNode);
7618                 }
7619             }
7620           std::vector<int> tmp3(2*(sz-1));
7621           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7622           std::copy(nodalConnBg+1,nodalConnEnd,it);
7623           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7624             {
7625               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7626               return false;
7627             }
7628           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7629             {
7630               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7631               return false;
7632             }
7633           else
7634             {
7635               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7636               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7637               return true;
7638             }
7639         }
7640       else
7641         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7642     }
7643   else
7644     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7645 }
7646
7647 /*!
7648  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7649  * 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.
7650  * 
7651  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7652  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7653  * \param [in,out] arr array in which the remove operation will be done.
7654  * \param [in,out] arrIndx array in the remove operation will modify
7655  * \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])
7656  * \return true if \b arr and \b arrIndx have been modified, false if not.
7657  */
7658 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7659 {
7660   if(!arrIndx || !arr)
7661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7662   if(offsetForRemoval<0)
7663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7664   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7665   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7666   int *arrIPtr=arrIndx->getPointer();
7667   *arrIPtr++=0;
7668   int previousArrI=0;
7669   const int *arrPtr=arr->begin();
7670   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7671   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7672     {
7673       if(*arrIPtr-previousArrI>offsetForRemoval)
7674         {
7675           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7676             {
7677               if(s.find(*work)==s.end())
7678                 arrOut.push_back(*work);
7679             }
7680         }
7681       previousArrI=*arrIPtr;
7682       *arrIPtr=(int)arrOut.size();
7683     }
7684   if(arr->getNumberOfTuples()==(int)arrOut.size())
7685     return false;
7686   arr->alloc((int)arrOut.size(),1);
7687   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7688   return true;
7689 }
7690
7691 /*!
7692  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7693  * (\ref numbering-indirect).
7694  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7695  * The selection of extraction is done standardly in new2old format.
7696  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7697  *
7698  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7699  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7700  * \param [in] arrIn arr origin array from which the extraction will be done.
7701  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7702  * \param [out] arrOut the resulting array
7703  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7704  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7705  */
7706 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7707                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7708 {
7709   if(!arrIn || !arrIndxIn)
7710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7711   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7712   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7714   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7715   const int *arrInPtr=arrIn->begin();
7716   const int *arrIndxPtr=arrIndxIn->begin();
7717   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7718   if(nbOfGrps<0)
7719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7720   int maxSizeOfArr=arrIn->getNumberOfTuples();
7721   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7722   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7723   arrIo->alloc((int)(sz+1),1);
7724   const int *idsIt=idsOfSelectBg;
7725   int *work=arrIo->getPointer();
7726   *work++=0;
7727   int lgth=0;
7728   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7729     {
7730       if(*idsIt>=0 && *idsIt<nbOfGrps)
7731         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7732       else
7733         {
7734           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7735           throw INTERP_KERNEL::Exception(oss.str());
7736         }
7737       if(lgth>=work[-1])
7738         *work=lgth;
7739       else
7740         {
7741           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7742           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7743           throw INTERP_KERNEL::Exception(oss.str());
7744         }
7745     }
7746   arro->alloc(lgth,1);
7747   work=arro->getPointer();
7748   idsIt=idsOfSelectBg;
7749   for(std::size_t i=0;i<sz;i++,idsIt++)
7750     {
7751       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7752         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7753       else
7754         {
7755           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7756           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7757           throw INTERP_KERNEL::Exception(oss.str());
7758         }
7759     }
7760   arrOut=arro.retn();
7761   arrIndexOut=arrIo.retn();
7762 }
7763
7764 /*!
7765  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7766  * (\ref numbering-indirect).
7767  * 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 ).
7768  * The selection of extraction is done standardly in new2old format.
7769  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7770  *
7771  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7772  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7773  * \param [in] idsOfSelectStep
7774  * \param [in] arrIn arr origin array from which the extraction will be done.
7775  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7776  * \param [out] arrOut the resulting array
7777  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7778  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7779  */
7780 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7781                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7782 {
7783   if(!arrIn || !arrIndxIn)
7784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7785   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7786   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7788   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7789   const int *arrInPtr=arrIn->begin();
7790   const int *arrIndxPtr=arrIndxIn->begin();
7791   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7792   if(nbOfGrps<0)
7793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7794   int maxSizeOfArr=arrIn->getNumberOfTuples();
7795   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7796   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7797   arrIo->alloc((int)(sz+1),1);
7798   int idsIt=idsOfSelectStart;
7799   int *work=arrIo->getPointer();
7800   *work++=0;
7801   int lgth=0;
7802   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7803     {
7804       if(idsIt>=0 && idsIt<nbOfGrps)
7805         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7806       else
7807         {
7808           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7809           throw INTERP_KERNEL::Exception(oss.str());
7810         }
7811       if(lgth>=work[-1])
7812         *work=lgth;
7813       else
7814         {
7815           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7816           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7817           throw INTERP_KERNEL::Exception(oss.str());
7818         }
7819     }
7820   arro->alloc(lgth,1);
7821   work=arro->getPointer();
7822   idsIt=idsOfSelectStart;
7823   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7824     {
7825       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7826         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
7827       else
7828         {
7829           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7830           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7831           throw INTERP_KERNEL::Exception(oss.str());
7832         }
7833     }
7834   arrOut=arro.retn();
7835   arrIndexOut=arrIo.retn();
7836 }
7837
7838 /*!
7839  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7840  * 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
7841  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7842  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7843  *
7844  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7845  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7846  * \param [in] arrIn arr origin array from which the extraction will be done.
7847  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7848  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7849  * \param [in] srcArrIndex index array of \b srcArr
7850  * \param [out] arrOut the resulting array
7851  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7852  * 
7853  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7854  */
7855 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7856                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7857                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7858 {
7859   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7861   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7862   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7863   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7864   std::vector<bool> v(nbOfTuples,true);
7865   int offset=0;
7866   const int *arrIndxInPtr=arrIndxIn->begin();
7867   const int *srcArrIndexPtr=srcArrIndex->begin();
7868   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7869     {
7870       if(*it>=0 && *it<nbOfTuples)
7871         {
7872           v[*it]=false;
7873           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7874         }
7875       else
7876         {
7877           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7878           throw INTERP_KERNEL::Exception(oss.str());
7879         }
7880     }
7881   srcArrIndexPtr=srcArrIndex->begin();
7882   arrIo->alloc(nbOfTuples+1,1);
7883   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7884   const int *arrInPtr=arrIn->begin();
7885   const int *srcArrPtr=srcArr->begin();
7886   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7887   int *arroPtr=arro->getPointer();
7888   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7889     {
7890       if(v[ii])
7891         {
7892           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7893           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7894         }
7895       else
7896         {
7897           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7898           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7899           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7900         }
7901     }
7902   arrOut=arro.retn();
7903   arrIndexOut=arrIo.retn();
7904 }
7905
7906 /*!
7907  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7908  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7909  *
7910  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7911  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7912  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7913  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7914  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7915  * \param [in] srcArrIndex index array of \b srcArr
7916  * 
7917  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7918  */
7919 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7920                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
7921 {
7922   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7924   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7925   const int *arrIndxInPtr=arrIndxIn->begin();
7926   const int *srcArrIndexPtr=srcArrIndex->begin();
7927   int *arrInOutPtr=arrInOut->getPointer();
7928   const int *srcArrPtr=srcArr->begin();
7929   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7930     {
7931       if(*it>=0 && *it<nbOfTuples)
7932         {
7933           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7934             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7935           else
7936             {
7937               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] !";
7938               throw INTERP_KERNEL::Exception(oss.str());
7939             }
7940         }
7941       else
7942         {
7943           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7944           throw INTERP_KERNEL::Exception(oss.str());
7945         }
7946     }
7947 }
7948
7949 /*!
7950  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7951  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7952  * 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]].
7953  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7954  * A negative value in \b arrIn means that it is ignored.
7955  * 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.
7956  * 
7957  * \param [in] arrIn arr origin array from which the extraction will be done.
7958  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7959  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7960  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
7961  */
7962 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
7963 {
7964   int seed=0,nbOfDepthPeelingPerformed=0;
7965   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
7966 }
7967
7968 /*!
7969  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7970  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7971  * 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]].
7972  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7973  * A negative value in \b arrIn means that it is ignored.
7974  * 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.
7975  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
7976  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
7977  * \param [in] arrIn arr origin array from which the extraction will be done.
7978  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7979  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
7980  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
7981  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7982  * \sa MEDCouplingUMesh::partitionBySpreadZone
7983  */
7984 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
7985 {
7986   nbOfDepthPeelingPerformed=0;
7987   if(!arrIndxIn)
7988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
7989   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7990   if(nbOfTuples<=0)
7991     {
7992       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
7993       return ret;
7994     }
7995   //
7996   std::vector<bool> fetched(nbOfTuples,false);
7997   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
7998 }
7999
8000
8001 /*!
8002  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8003  * 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
8004  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8005  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8006  *
8007  * \param [in] start begin of set of ids of the input extraction (included)
8008  * \param [in] end end of set of ids of the input extraction (excluded)
8009  * \param [in] step step of the set of ids in range mode.
8010  * \param [in] arrIn arr origin array from which the extraction will be done.
8011  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8012  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8013  * \param [in] srcArrIndex index array of \b srcArr
8014  * \param [out] arrOut the resulting array
8015  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8016  * 
8017  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8018  */
8019 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8020                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8021                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
8022 {
8023   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8024     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
8025   MCAuto<DataArrayInt> arro=DataArrayInt::New();
8026   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
8027   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8028   int offset=0;
8029   const int *arrIndxInPtr=arrIndxIn->begin();
8030   const int *srcArrIndexPtr=srcArrIndex->begin();
8031   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
8032   int it=start;
8033   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8034     {
8035       if(it>=0 && it<nbOfTuples)
8036         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8037       else
8038         {
8039           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8040           throw INTERP_KERNEL::Exception(oss.str());
8041         }
8042     }
8043   srcArrIndexPtr=srcArrIndex->begin();
8044   arrIo->alloc(nbOfTuples+1,1);
8045   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8046   const int *arrInPtr=arrIn->begin();
8047   const int *srcArrPtr=srcArr->begin();
8048   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8049   int *arroPtr=arro->getPointer();
8050   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8051     {
8052       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8053       if(pos<0)
8054         {
8055           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8056           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8057         }
8058       else
8059         {
8060           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8061           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8062         }
8063     }
8064   arrOut=arro.retn();
8065   arrIndexOut=arrIo.retn();
8066 }
8067
8068 /*!
8069  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8070  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8071  *
8072  * \param [in] start begin of set of ids of the input extraction (included)
8073  * \param [in] end end of set of ids of the input extraction (excluded)
8074  * \param [in] step step of the set of ids in range mode.
8075  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8076  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8077  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8078  * \param [in] srcArrIndex index array of \b srcArr
8079  * 
8080  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8081  */
8082 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8083                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8084 {
8085   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8087   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8088   const int *arrIndxInPtr=arrIndxIn->begin();
8089   const int *srcArrIndexPtr=srcArrIndex->begin();
8090   int *arrInOutPtr=arrInOut->getPointer();
8091   const int *srcArrPtr=srcArr->begin();
8092   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8093   int it=start;
8094   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8095     {
8096       if(it>=0 && it<nbOfTuples)
8097         {
8098           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8099             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8100           else
8101             {
8102               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8103               throw INTERP_KERNEL::Exception(oss.str());
8104             }
8105         }
8106       else
8107         {
8108           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8109           throw INTERP_KERNEL::Exception(oss.str());
8110         }
8111     }
8112 }
8113
8114 /*!
8115  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8116  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8117  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8118  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8119  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8120  * 
8121  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8122  */
8123 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8124 {
8125   checkFullyDefined();
8126   int mdim=getMeshDimension();
8127   int spaceDim=getSpaceDimension();
8128   if(mdim!=spaceDim)
8129     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8130   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8131   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8132   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8133   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8134   ret->setCoords(getCoords());
8135   ret->allocateCells((int)partition.size());
8136   //
8137   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8138     {
8139       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8140       MCAuto<DataArrayInt> cell;
8141       switch(mdim)
8142       {
8143         case 2:
8144           cell=tmp->buildUnionOf2DMesh();
8145           break;
8146         case 3:
8147           cell=tmp->buildUnionOf3DMesh();
8148           break;
8149         default:
8150           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8151       }
8152
8153       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8154     }
8155   //
8156   ret->finishInsertingCells();
8157   return ret.retn();
8158 }
8159
8160 /*!
8161  * This method partitions \b this into contiguous zone.
8162  * This method only needs a well defined connectivity. Coordinates are not considered here.
8163  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8164  */
8165 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8166 {
8167   DataArrayInt *neigh=0,*neighI=0;
8168   computeNeighborsOfCells(neigh,neighI);
8169   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8170   return PartitionBySpreadZone(neighAuto,neighIAuto);
8171 }
8172
8173 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8174 {
8175   if(!arrIn || !arrIndxIn)
8176     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8177   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8178   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8179   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8180     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8181   int nbOfCellsCur(nbOfTuples-1);
8182   std::vector<DataArrayInt *> ret;
8183   if(nbOfCellsCur<=0)
8184     return ret;
8185   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8186   std::vector< MCAuto<DataArrayInt> > ret2;
8187   int seed=0;
8188   while(seed<nbOfCellsCur)
8189     {
8190       int nbOfPeelPerformed=0;
8191       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8192       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8193     }
8194   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8195     ret.push_back((*it).retn());
8196   return ret;
8197 }
8198
8199 /*!
8200  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8201  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8202  *
8203  * \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.
8204  * \return a newly allocated DataArrayInt to be managed by the caller.
8205  * \throw In case of \a code has not the right format (typically of size 3*n)
8206  */
8207 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8208 {
8209   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8210   std::size_t nb=code.size()/3;
8211   if(code.size()%3!=0)
8212     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8213   ret->alloc((int)nb,2);
8214   int *retPtr=ret->getPointer();
8215   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8216     {
8217       retPtr[0]=code[3*i+2];
8218       retPtr[1]=code[3*i+2]+code[3*i+1];
8219     }
8220   return ret.retn();
8221 }
8222
8223 /*!
8224  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8225  * All cells in \a this are expected to be linear 3D cells.
8226  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8227  * It leads to an increase to number of cells.
8228  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8229  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8230  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8231  *
8232  * \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.
8233  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8234  * \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. 
8235  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8236  *          an id of old cell producing it. The caller is to delete this array using
8237  *         decrRef() as it is no more needed.
8238  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8239  *
8240  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
8241  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8242  * 
8243  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8244  * \throw If \a this is not fully constituted with linear 3D cells.
8245  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8246  */
8247 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8248 {
8249   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8250   checkConnectivityFullyDefined();
8251   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8252     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8253   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8254   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8255   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8256   int *retPt(ret->getPointer());
8257   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8258   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8259   const int *oldc(_nodal_connec->begin());
8260   const int *oldci(_nodal_connec_index->begin());
8261   const double *coords(_coords->begin());
8262   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8263     {
8264       std::vector<int> a; std::vector<double> b;
8265       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8266       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8267       const int *aa(&a[0]);
8268       if(!b.empty())
8269         {
8270           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8271             if(*it<0)
8272               *it=(-(*(it))-1+nbNodes);
8273           addPts->insertAtTheEnd(b.begin(),b.end());
8274           nbNodes+=(int)b.size()/3;
8275         }
8276       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8277         newConn->insertAtTheEnd(aa,aa+4);
8278     }
8279   if(!addPts->empty())
8280     {
8281       addPts->rearrange(3);
8282       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8283       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8284       ret0->setCoords(addPts);
8285     }
8286   else
8287     {
8288       nbOfAdditionalPoints=0;
8289       ret0->setCoords(getCoords());
8290     }
8291   ret0->setNodalConnectivity(newConn);
8292   //
8293   ret->computeOffsetsFull();
8294   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8295   return ret0.retn();
8296 }
8297
8298 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8299     _own_cell(true),_cell_id(-1),_nb_cell(0)
8300 {
8301   if(mesh)
8302     {
8303       mesh->incrRef();
8304       _nb_cell=mesh->getNumberOfCells();
8305     }
8306 }
8307
8308 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8309 {
8310   if(_mesh)
8311     _mesh->decrRef();
8312   if(_own_cell)
8313     delete _cell;
8314 }
8315
8316 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8317     _own_cell(false),_cell_id(bg-1),
8318     _nb_cell(end)
8319 {
8320   if(mesh)
8321     mesh->incrRef();
8322 }
8323
8324 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8325 {
8326   _cell_id++;
8327   if(_cell_id<_nb_cell)
8328     {
8329       _cell->next();
8330       return _cell;
8331     }
8332   else
8333     return 0;
8334 }
8335
8336 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8337 {
8338   if(_mesh)
8339     _mesh->incrRef();
8340 }
8341
8342 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8343 {
8344   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8345 }
8346
8347 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8348 {
8349   if(_mesh)
8350     _mesh->decrRef();
8351 }
8352
8353 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8354     _itc(itc),
8355     _bg(bg),_end(end)
8356 {
8357   if(_mesh)
8358     _mesh->incrRef();
8359 }
8360
8361 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8362 {
8363   if(_mesh)
8364     _mesh->decrRef();
8365 }
8366
8367 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8368 {
8369   return _type;
8370 }
8371
8372 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8373 {
8374   return _end-_bg;
8375 }
8376
8377 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8378 {
8379   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8380 }
8381
8382 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8383 {
8384   if(mesh)
8385     {
8386       mesh->incrRef();
8387       _nb_cell=mesh->getNumberOfCells();
8388     }
8389 }
8390
8391 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8392 {
8393   if(_mesh)
8394     _mesh->decrRef();
8395   delete _cell;
8396 }
8397
8398 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8399 {
8400   const int *c=_mesh->getNodalConnectivity()->begin();
8401   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8402   if(_cell_id<_nb_cell)
8403     {
8404       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8405       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8406       int startId=_cell_id;
8407       _cell_id+=nbOfElems;
8408       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8409     }
8410   else
8411     return 0;
8412 }
8413
8414 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8415 {
8416   if(mesh)
8417     {
8418       _conn=mesh->getNodalConnectivity()->getPointer();
8419       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8420     }
8421 }
8422
8423 void MEDCouplingUMeshCell::next()
8424 {
8425   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8426     {
8427       _conn+=_conn_lgth;
8428       _conn_indx++;
8429     }
8430   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8431 }
8432
8433 std::string MEDCouplingUMeshCell::repr() const
8434 {
8435   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8436     {
8437       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8438       oss << " : ";
8439       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8440       return oss.str();
8441     }
8442   else
8443     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8444 }
8445
8446 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8447 {
8448   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8449     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8450   else
8451     return INTERP_KERNEL::NORM_ERROR;
8452 }
8453
8454 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8455 {
8456   lgth=_conn_lgth;
8457   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8458     return _conn;
8459   else
8460     return 0;
8461 }