Salome HOME
87c0118f02c07dc438dc139596d2e00a4fe12faf
[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->getConstPointer();
597   const int *connIndex=_nodal_connec_index->getConstPointer();
598   int nbOfCells=getNumberOfCells();
599   int nbOfEltsInRevNodal=0;
600   for(int eltId=0;eltId<nbOfCells;eltId++)
601     {
602       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
603       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
604       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
605         if(*iter>=0)//for polyhedrons
606           {
607             nbOfEltsInRevNodal++;
608             revNodalIndxPtr[(*iter)+1]++;
609           }
610     }
611   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
612   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
613   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
614   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
615   for(int eltId=0;eltId<nbOfCells;eltId++)
616     {
617       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620         if(*iter>=0)//for polyhedrons
621           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
622     }
623 }
624
625 /*!
626  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
627  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
628  * describing correspondence between cells of \a this and the result meshes are
629  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
630  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
631  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
632  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
633  * \warning For speed reasons, this method does not check if node ids in the nodal
634  *          connectivity correspond to the size of node coordinates array.
635  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
636  *          to write this mesh to the MED file, its cells must be sorted using
637  *          sortCellsInMEDFileFrmt().
638  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
639  *         each cell of \a this mesh.
640  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
641  *        dividing cell ids in \a desc into groups each referring to one
642  *        cell of \a this mesh. Its every element (except the last one) is an index
643  *        pointing to the first id of a group of cells. For example cells of the
644  *        result mesh bounding the cell #1 of \a this mesh are described by following
645  *        range of indices:
646  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
647  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
648  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
649  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
650  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
651  *         by each cell of the result mesh.
652  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
653  *        in the result mesh,
654  *        dividing cell ids in \a revDesc into groups each referring to one
655  *        cell of the result mesh the same way as \a descIndx divides \a desc.
656  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
657  *        delete this mesh using decrRef() as it is no more needed.
658  *  \throw If the coordinates array is not set.
659  *  \throw If the nodal connectivity of cells is node defined.
660  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
661  *         revDescIndx == NULL.
662  * 
663  *  \if ENABLE_EXAMPLES
664  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
665  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
666  *  \endif
667  * \sa buildDescendingConnectivity2()
668  */
669 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
670 {
671   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
672 }
673
674 /*!
675  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
676  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
677  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
678  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
679  * \sa MEDCouplingUMesh::buildDescendingConnectivity
680  */
681 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
682 {
683   checkFullyDefined();
684   if(getMeshDimension()!=3)
685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
686   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
687 }
688
689 /*!
690  * 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.
691  * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
692  * 
693  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
694  */
695 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
696 {
697    checkFullyDefined();
698    switch(getMeshDimension())
699      {
700      case 2:
701        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
702      case 3:
703        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
704      default:
705        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
706      }
707 }
708
709 /*!
710  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
711  * this->getMeshDimension(), that bound cells of \a this mesh. In
712  * addition arrays describing correspondence between cells of \a this and the result
713  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
714  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
715  *  mesh. This method differs from buildDescendingConnectivity() in that apart
716  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
717  * result meshes. So a positive id means that order of nodes in corresponding cells
718  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
719  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
720  * i.e. cell ids are one-based.
721  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
722  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
723  * \warning For speed reasons, this method does not check if node ids in the nodal
724  *          connectivity correspond to the size of node coordinates array.
725  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
726  *          to write this mesh to the MED file, its cells must be sorted using
727  *          sortCellsInMEDFileFrmt().
728  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
729  *         each cell of \a this mesh.
730  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
731  *        dividing cell ids in \a desc into groups each referring to one
732  *        cell of \a this mesh. Its every element (except the last one) is an index
733  *        pointing to the first id of a group of cells. For example cells of the
734  *        result mesh bounding the cell #1 of \a this mesh are described by following
735  *        range of indices:
736  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
737  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
738  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
739  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
740  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
741  *         by each cell of the result mesh.
742  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
743  *        in the result mesh,
744  *        dividing cell ids in \a revDesc into groups each referring to one
745  *        cell of the result mesh the same way as \a descIndx divides \a desc.
746  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
747  *        shares the node coordinates array with \a this mesh. The caller is to
748  *        delete this mesh using decrRef() as it is no more needed.
749  *  \throw If the coordinates array is not set.
750  *  \throw If the nodal connectivity of cells is node defined.
751  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
752  *         revDescIndx == NULL.
753  * 
754  *  \if ENABLE_EXAMPLES
755  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
756  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
757  *  \endif
758  * \sa buildDescendingConnectivity()
759  */
760 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
761 {
762   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
763 }
764
765 /*!
766  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
767  * For speed reasons no check of this will be done. This method calls
768  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
769  * This method lists cell by cell in \b this which are its neighbors. To compute the result
770  * only connectivities are considered.
771  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
772  * The format of return is hence \ref numbering-indirect.
773  *
774  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
775  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
776  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
777  * is equal to the last values in \b neighborsIndx.
778  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
779  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
780  */
781 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
782 {
783   MCAuto<DataArrayInt> desc=DataArrayInt::New();
784   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
785   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
786   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
787   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
788   meshDM1=0;
789   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
790 }
791
792 void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayInt *nodeNeigh, const DataArrayInt *nodeNeighI, MCAuto<DataArrayInt>& cellNeigh, MCAuto<DataArrayInt>& cellNeighIndex) const
793 {
794   if(!nodeNeigh || !nodeNeighI)
795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !");
796   checkConsistencyLight();
797   nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated();
798   nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh");
799   nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index");
800   nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length");
801   int nbCells(getNumberOfCells());
802   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin());
803   cellNeigh=DataArrayInt::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayInt::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0);
804   for(int i=0;i<nbCells;i++)
805     {
806       std::set<int> s;
807       for(const int *it=c+ci[i]+1;it!=c+ci[i+1];it++)
808         if(*it>=0)
809           s.insert(ne+nei[*it],ne+nei[*it+1]);
810       s.erase(i);
811       cellNeigh->insertAtTheEnd(s.begin(),s.end());
812       cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples());
813     }
814 }
815
816 /*!
817  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
818  * of MEDCouplingUMesh::computeNeighborsOfCells.
819  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
820  * typically the case to extract a set a neighbours,
821  * excluding a set of meshdim-1 cells in input descending connectivity.
822  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
823  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
824  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
825  * are considered.
826  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
827  *
828  * \param [in] desc descending connectivity array.
829  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
830  * \param [in] revDesc reverse descending connectivity array.
831  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
832  * \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
833  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
834  * \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.
835  */
836 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
837                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
838 {
839   if(!desc || !descIndx || !revDesc || !revDescIndx)
840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
841   const int *descPtr=desc->getConstPointer();
842   const int *descIPtr=descIndx->getConstPointer();
843   const int *revDescPtr=revDesc->getConstPointer();
844   const int *revDescIPtr=revDescIndx->getConstPointer();
845   //
846   int nbCells=descIndx->getNumberOfTuples()-1;
847   MCAuto<DataArrayInt> out0=DataArrayInt::New();
848   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
849   int *out1Ptr=out1->getPointer();
850   *out1Ptr++=0;
851   out0->reserve(desc->getNumberOfTuples());
852   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
853     {
854       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
855         {
856           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
857           s.erase(i);
858           out0->insertAtTheEnd(s.begin(),s.end());
859         }
860       *out1Ptr=out0->getNumberOfTuples();
861     }
862   neighbors=out0.retn();
863   neighborsIndx=out1.retn();
864 }
865
866 /*!
867  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
868  * For speed reasons no check of this will be done. This method calls
869  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
870  * This method lists node by node in \b this which are its neighbors. To compute the result
871  * only connectivities are considered.
872  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
873  *
874  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
875  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
876  * parameter allows to select the right part in this array (\ref numbering-indirect).
877  * The number of tuples is equal to the last values in \b neighborsIndx.
878  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
879  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
880  */
881 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
882 {
883   checkFullyDefined();
884   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
885   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
886   MCAuto<MEDCouplingUMesh> mesh1D;
887   switch(mdim)
888   {
889     case 3:
890       {
891         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
892         break;
893       }
894     case 2:
895       {
896         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
897         break;
898       }
899     case 1:
900       {
901         mesh1D=const_cast<MEDCouplingUMesh *>(this);
902         mesh1D->incrRef();
903         break;
904       }
905     default:
906       {
907         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
908       }
909   }
910   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
911   mesh1D->getReverseNodalConnectivity(desc,descIndx);
912   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
913   ret0->alloc(desc->getNumberOfTuples(),1);
914   int *r0Pt(ret0->getPointer());
915   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
916   for(int i=0;i<nbNodes;i++,rni++)
917     {
918       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
919         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
920     }
921   neighbors=ret0.retn();
922   neighborsIdx=descIndx.retn();
923 }
924
925 /*!
926  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
927  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
928  * array of cell ids. Pay attention that after conversion all algorithms work slower
929  * with \a this mesh than before conversion. <br> If an exception is thrown during the
930  * conversion due presence of invalid ids in the array of cells to convert, as a
931  * result \a this mesh contains some already converted elements. In this case the 2D
932  * mesh remains valid but 3D mesh becomes \b inconsistent!
933  *  \warning This method can significantly modify the order of geometric types in \a this,
934  *          hence, to write this mesh to the MED file, its cells must be sorted using
935  *          sortCellsInMEDFileFrmt().
936  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
937  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
938  *         cellIdsToConvertBg.
939  *  \throw If the coordinates array is not set.
940  *  \throw If the nodal connectivity of cells is node defined.
941  *  \throw If dimension of \a this mesh is not either 2 or 3.
942  *
943  *  \if ENABLE_EXAMPLES
944  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
945  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
946  *  \endif
947  */
948 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
949 {
950   checkFullyDefined();
951   int dim=getMeshDimension();
952   if(dim<2 || dim>3)
953     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
954   int nbOfCells(getNumberOfCells());
955   if(dim==2)
956     {
957       const int *connIndex=_nodal_connec_index->getConstPointer();
958       int *conn=_nodal_connec->getPointer();
959       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
960         {
961           if(*iter>=0 && *iter<nbOfCells)
962             {
963               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
964               if(!cm.isQuadratic())
965                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
966               else
967                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
968             }
969           else
970             {
971               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
972               oss << " in range [0," << nbOfCells << ") !";
973               throw INTERP_KERNEL::Exception(oss.str());
974             }
975         }
976     }
977   else
978     {
979       int *connIndex(_nodal_connec_index->getPointer());
980       const int *connOld(_nodal_connec->getConstPointer());
981       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
982       std::vector<bool> toBeDone(nbOfCells,false);
983       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
984         {
985           if(*iter>=0 && *iter<nbOfCells)
986             toBeDone[*iter]=true;
987           else
988             {
989               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
990               oss << " in range [0," << nbOfCells << ") !";
991               throw INTERP_KERNEL::Exception(oss.str());
992             }
993         }
994       for(int cellId=0;cellId<nbOfCells;cellId++)
995         {
996           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
997           int lgthOld(posP1-pos-1);
998           if(toBeDone[cellId])
999             {
1000               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1001               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1002               int *tmp(new int[nbOfFaces*lgthOld+1]);
1003               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1004               for(unsigned j=0;j<nbOfFaces;j++)
1005                 {
1006                   INTERP_KERNEL::NormalizedCellType type;
1007                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1008                   work+=offset;
1009                   *work++=-1;
1010                 }
1011               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1012               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1013               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1014               delete [] tmp;
1015             }
1016           else
1017             {
1018               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1019               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1020             }
1021         }
1022       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1023     }
1024   computeTypes();
1025 }
1026
1027 /*!
1028  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1029  * polyhedrons (if \a this is a 3D mesh).
1030  *  \warning As this method is purely for user-friendliness and no optimization is
1031  *          done to avoid construction of a useless vector, this method can be costly
1032  *          in memory.
1033  *  \throw If the coordinates array is not set.
1034  *  \throw If the nodal connectivity of cells is node defined.
1035  *  \throw If dimension of \a this mesh is not either 2 or 3.
1036  */
1037 void MEDCouplingUMesh::convertAllToPoly()
1038 {
1039   int nbOfCells=getNumberOfCells();
1040   std::vector<int> cellIds(nbOfCells);
1041   for(int i=0;i<nbOfCells;i++)
1042     cellIds[i]=i;
1043   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1044 }
1045
1046 /*!
1047  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1048  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1049  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1050  * base facet of the volume and the second half of nodes describes an opposite facet
1051  * having the same number of nodes as the base one. This method converts such
1052  * connectivity to a valid polyhedral format where connectivity of each facet is
1053  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1054  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1055  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1056  * a correct orientation of the first facet of a polyhedron, else orientation of a
1057  * corrected cell is reverse.<br>
1058  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1059  * it releases the user from boring description of polyhedra connectivity in the valid
1060  * format.
1061  *  \throw If \a this->getMeshDimension() != 3.
1062  *  \throw If \a this->getSpaceDimension() != 3.
1063  *  \throw If the nodal connectivity of cells is not defined.
1064  *  \throw If the coordinates array is not set.
1065  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1066  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1067  *
1068  *  \if ENABLE_EXAMPLES
1069  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1070  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1071  *  \endif
1072  */
1073 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1074 {
1075   checkFullyDefined();
1076   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1077     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1078   int nbOfCells=getNumberOfCells();
1079   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1080   newCi->alloc(nbOfCells+1,1);
1081   int *newci=newCi->getPointer();
1082   const int *ci=_nodal_connec_index->getConstPointer();
1083   const int *c=_nodal_connec->getConstPointer();
1084   newci[0]=0;
1085   for(int i=0;i<nbOfCells;i++)
1086     {
1087       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1088       if(type==INTERP_KERNEL::NORM_POLYHED)
1089         {
1090           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1091             {
1092               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1093               throw INTERP_KERNEL::Exception(oss.str());
1094             }
1095           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1096           if(n2%2!=0)
1097             {
1098               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 !";
1099               throw INTERP_KERNEL::Exception(oss.str());
1100             }
1101           int n1=(int)(n2/2);
1102           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)
1103         }
1104       else
1105         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1106     }
1107   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1108   newC->alloc(newci[nbOfCells],1);
1109   int *newc=newC->getPointer();
1110   for(int i=0;i<nbOfCells;i++)
1111     {
1112       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1113       if(type==INTERP_KERNEL::NORM_POLYHED)
1114         {
1115           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1116           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1117           *newc++=-1;
1118           for(std::size_t j=0;j<n1;j++)
1119             {
1120               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1121               newc[n1+5*j]=-1;
1122               newc[n1+5*j+1]=c[ci[i]+1+j];
1123               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1124               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1125               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1126             }
1127           newc+=n1*6;
1128         }
1129       else
1130         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1131     }
1132   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1133   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1134 }
1135
1136
1137 /*!
1138  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1139  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1140  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1141  *          to write this mesh to the MED file, its cells must be sorted using
1142  *          sortCellsInMEDFileFrmt().
1143  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1144  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1145  * \return \c true if at least one cell has been converted, \c false else. In the
1146  *         last case the nodal connectivity remains unchanged.
1147  * \throw If the coordinates array is not set.
1148  * \throw If the nodal connectivity of cells is not defined.
1149  * \throw If \a this->getMeshDimension() < 0.
1150  */
1151 bool MEDCouplingUMesh::unPolyze()
1152 {
1153   checkFullyDefined();
1154   int mdim=getMeshDimension();
1155   if(mdim<0)
1156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1157   if(mdim<=1)
1158     return false;
1159   int nbOfCells=getNumberOfCells();
1160   if(nbOfCells<1)
1161     return false;
1162   int initMeshLgth=getNodalConnectivityArrayLen();
1163   int *conn=_nodal_connec->getPointer();
1164   int *index=_nodal_connec_index->getPointer();
1165   int posOfCurCell=0;
1166   int newPos=0;
1167   int lgthOfCurCell;
1168   bool ret=false;
1169   for(int i=0;i<nbOfCells;i++)
1170     {
1171       lgthOfCurCell=index[i+1]-posOfCurCell;
1172       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1173       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1174       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1175       int newLgth;
1176       if(cm.isDynamic())
1177         {
1178           switch(cm.getDimension())
1179           {
1180             case 2:
1181               {
1182                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1183                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1184                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1185                 break;
1186               }
1187             case 3:
1188               {
1189                 int nbOfFaces,lgthOfPolyhConn;
1190                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1191                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1192                 break;
1193               }
1194             case 1:
1195               {
1196                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1197                 break;
1198               }
1199           }
1200           ret=ret || (newType!=type);
1201           conn[newPos]=newType;
1202           newPos+=newLgth+1;
1203           posOfCurCell=index[i+1];
1204           index[i+1]=newPos;
1205         }
1206       else
1207         {
1208           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1209           newPos+=lgthOfCurCell;
1210           posOfCurCell+=lgthOfCurCell;
1211           index[i+1]=newPos;
1212         }
1213     }
1214   if(newPos!=initMeshLgth)
1215     _nodal_connec->reAlloc(newPos);
1216   if(ret)
1217     computeTypes();
1218   return ret;
1219 }
1220
1221 /*!
1222  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1223  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1224  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1225  *
1226  * \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 
1227  *             precision.
1228  */
1229 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1230 {
1231   checkFullyDefined();
1232   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1233     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1234   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1235   coords->recenterForMaxPrecision(eps);
1236   //
1237   int nbOfCells=getNumberOfCells();
1238   const int *conn=_nodal_connec->getConstPointer();
1239   const int *index=_nodal_connec_index->getConstPointer();
1240   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1241   connINew->alloc(nbOfCells+1,1);
1242   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1243   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1244   bool changed=false;
1245   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1246     {
1247       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1248         {
1249           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1250           changed=true;
1251         }
1252       else
1253         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1254       *connINewPtr=connNew->getNumberOfTuples();
1255     }
1256   if(changed)
1257     setConnectivity(connNew,connINew,false);
1258 }
1259
1260 /*!
1261  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1262  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1263  * the format of the returned DataArrayInt instance.
1264  * 
1265  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1266  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1267  */
1268 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1269 {
1270   checkConnectivityFullyDefined();
1271   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1272   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1273   std::vector<bool> retS(maxElt,false);
1274   computeNodeIdsAlg(retS);
1275   return DataArrayInt::BuildListOfSwitchedOn(retS);
1276 }
1277
1278 /*!
1279  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1280  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1281  */
1282 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1283 {
1284   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1285   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1286   for(int i=0;i<nbOfCells;i++)
1287     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1288       if(conn[j]>=0)
1289         {
1290           if(conn[j]<nbOfNodes)
1291             nodeIdsInUse[conn[j]]=true;
1292           else
1293             {
1294               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1295               throw INTERP_KERNEL::Exception(oss.str());
1296             }
1297         }
1298 }
1299
1300 /// @cond INTERNAL
1301
1302 struct MEDCouplingAccVisit
1303 {
1304   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1305   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1306   int _new_nb_of_nodes;
1307 };
1308
1309 /// @endcond
1310
1311 /*!
1312  * Finds nodes not used in any cell and returns an array giving a new id to every node
1313  * by excluding the unused nodes, for which the array holds -1. The result array is
1314  * a mapping in "Old to New" mode. 
1315  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1316  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1317  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1318  *          if the node is unused or a new id else. The caller is to delete this
1319  *          array using decrRef() as it is no more needed.  
1320  *  \throw If the coordinates array is not set.
1321  *  \throw If the nodal connectivity of cells is not defined.
1322  *  \throw If the nodal connectivity includes an invalid id.
1323  *
1324  *  \if ENABLE_EXAMPLES
1325  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1326  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1327  *  \endif
1328  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1329  */
1330 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1331 {
1332   nbrOfNodesInUse=-1;
1333   int nbOfNodes(getNumberOfNodes());
1334   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1335   ret->alloc(nbOfNodes,1);
1336   int *traducer=ret->getPointer();
1337   std::fill(traducer,traducer+nbOfNodes,-1);
1338   int nbOfCells=getNumberOfCells();
1339   const int *connIndex=_nodal_connec_index->getConstPointer();
1340   const int *conn=_nodal_connec->getConstPointer();
1341   for(int i=0;i<nbOfCells;i++)
1342     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1343       if(conn[j]>=0)
1344         {
1345           if(conn[j]<nbOfNodes)
1346             traducer[conn[j]]=1;
1347           else
1348             {
1349               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1350               throw INTERP_KERNEL::Exception(oss.str());
1351             }
1352         }
1353   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1354   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1355   return ret.retn();
1356 }
1357
1358 /*!
1359  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1360  * For each cell in \b this the number of nodes constituting cell is computed.
1361  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1362  * So for pohyhedrons some nodes can be counted several times in the returned result.
1363  * 
1364  * \return a newly allocated array
1365  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1366  */
1367 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1368 {
1369   checkConnectivityFullyDefined();
1370   int nbOfCells=getNumberOfCells();
1371   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1372   ret->alloc(nbOfCells,1);
1373   int *retPtr=ret->getPointer();
1374   const int *conn=getNodalConnectivity()->getConstPointer();
1375   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1376   for(int i=0;i<nbOfCells;i++,retPtr++)
1377     {
1378       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1379         *retPtr=connI[i+1]-connI[i]-1;
1380       else
1381         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1382     }
1383   return ret.retn();
1384 }
1385
1386 /*!
1387  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1388  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1389  *
1390  * \return DataArrayInt * - new object to be deallocated by the caller.
1391  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1392  */
1393 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1394 {
1395   checkConnectivityFullyDefined();
1396   int nbOfCells=getNumberOfCells();
1397   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1398   ret->alloc(nbOfCells,1);
1399   int *retPtr=ret->getPointer();
1400   const int *conn=getNodalConnectivity()->getConstPointer();
1401   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1402   for(int i=0;i<nbOfCells;i++,retPtr++)
1403     {
1404       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1405       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1406         *retPtr=(int)s.size();
1407       else
1408         {
1409           s.erase(-1);
1410           *retPtr=(int)s.size();
1411         }
1412     }
1413   return ret.retn();
1414 }
1415
1416 /*!
1417  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1418  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1419  * 
1420  * \return a newly allocated array
1421  */
1422 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1423 {
1424   checkConnectivityFullyDefined();
1425   int nbOfCells=getNumberOfCells();
1426   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1427   ret->alloc(nbOfCells,1);
1428   int *retPtr=ret->getPointer();
1429   const int *conn=getNodalConnectivity()->getConstPointer();
1430   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1431   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1432     {
1433       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1434       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1435     }
1436   return ret.retn();
1437 }
1438
1439 /*!
1440  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1441  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1442  * array mean that the corresponding old node is no more used. 
1443  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1444  *           this->getNumberOfNodes() before call of this method. The caller is to
1445  *           delete this array using decrRef() as it is no more needed. 
1446  *  \throw If the coordinates array is not set.
1447  *  \throw If the nodal connectivity of cells is not defined.
1448  *  \throw If the nodal connectivity includes an invalid id.
1449  *  \sa areAllNodesFetched
1450  *
1451  *  \if ENABLE_EXAMPLES
1452  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1453  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1454  *  \endif
1455  */
1456 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1457 {
1458   return MEDCouplingPointSet::zipCoordsTraducer();
1459 }
1460
1461 /*!
1462  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1463  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1464  */
1465 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1466 {
1467   switch(compType)
1468   {
1469     case 0:
1470       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1471     case 1:
1472       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1473     case 2:
1474       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1475     case 3:
1476       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1477     case 7:
1478       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1479   }
1480   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1481 }
1482
1483 /*!
1484  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1485  */
1486 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1487 {
1488   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1489     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1490   return 0;
1491 }
1492
1493 /*!
1494  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1495  */
1496 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1497 {
1498   int sz=connI[cell1+1]-connI[cell1];
1499   if(sz==connI[cell2+1]-connI[cell2])
1500     {
1501       if(conn[connI[cell1]]==conn[connI[cell2]])
1502         {
1503           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1504           unsigned dim=cm.getDimension();
1505           if(dim!=3)
1506             {
1507               if(dim!=1)
1508                 {
1509                   int sz1=2*(sz-1);
1510                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1511                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1512                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1513                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1514                   return work!=tmp+sz1?1:0;
1515                 }
1516               else
1517                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1518             }
1519           else
1520             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1521         }
1522     }
1523   return 0;
1524 }
1525
1526 /*!
1527  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1528  */
1529 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1530 {
1531   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1532     {
1533       if(conn[connI[cell1]]==conn[connI[cell2]])
1534         {
1535           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1536           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1537           return s1==s2?1:0;
1538         }
1539     }
1540   return 0;
1541 }
1542
1543 /*!
1544  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1545  */
1546 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1547 {
1548   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1549     {
1550       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1551       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1552       return s1==s2?1:0;
1553     }
1554   return 0;
1555 }
1556
1557 /*!
1558  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1559  */
1560 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1561 {
1562   int sz=connI[cell1+1]-connI[cell1];
1563   if(sz==connI[cell2+1]-connI[cell2])
1564     {
1565       if(conn[connI[cell1]]==conn[connI[cell2]])
1566         {
1567           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1568           unsigned dim=cm.getDimension();
1569           if(dim!=3)
1570             {
1571               if(dim!=1)
1572                 {
1573                   int sz1=2*(sz-1);
1574                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1575                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1576                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1577                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1578                   if(work!=tmp+sz1)
1579                     return 1;
1580                   else
1581                     {
1582                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1583                       std::reverse_iterator<int *> it2((int *)tmp);
1584                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1585                         return 2;
1586                       else
1587                         return 0;
1588                     }
1589
1590                   return work!=tmp+sz1?1:0;
1591                 }
1592               else
1593                 {//case of SEG2 and SEG3
1594                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1595                     return 1;
1596                   if(!cm.isQuadratic())
1597                     {
1598                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1599                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1600                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1601                         return 2;
1602                       return 0;
1603                     }
1604                   else
1605                     {
1606                       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])
1607                         return 2;
1608                       return 0;
1609                     }
1610                 }
1611             }
1612           else
1613             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1614         }
1615     }
1616   return 0;
1617 }
1618
1619
1620 /*!
1621  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1622  * by \a compType.
1623  * This method keeps the coordiantes of \a this. This method is time consuming.
1624  *
1625  * \param [in] compType input specifying the technique used to compare cells each other.
1626  *   - 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.
1627  *   - 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)
1628  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1629  *   - 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
1630  * can be used for users not sensitive to orientation of cell
1631  * \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.
1632  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1633  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1634  * \return the correspondance array old to new in a newly allocated array.
1635  * 
1636  */
1637 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1638 {
1639   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1640   getReverseNodalConnectivity(revNodal,revNodalI);
1641   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1642 }
1643
1644 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1645                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1646 {
1647   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1648   int nbOfCells=nodalI->getNumberOfTuples()-1;
1649   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1650   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1651   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1652   std::vector<bool> isFetched(nbOfCells,false);
1653   if(startCellId==0)
1654     {
1655       for(int i=0;i<nbOfCells;i++)
1656         {
1657           if(!isFetched[i])
1658             {
1659               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1660               std::vector<int> v,v2;
1661               if(connOfNode!=connPtr+connIPtr[i+1])
1662                 {
1663                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1664                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1665                   connOfNode++;
1666                 }
1667               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1668                 if(*connOfNode>=0)
1669                   {
1670                     v=v2;
1671                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1672                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1673                     v2.resize(std::distance(v2.begin(),it));
1674                   }
1675               if(v2.size()>1)
1676                 {
1677                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1678                     {
1679                       int pos=commonCellsI->back();
1680                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1681                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1682                         isFetched[*it]=true;
1683                     }
1684                 }
1685             }
1686         }
1687     }
1688   else
1689     {
1690       for(int i=startCellId;i<nbOfCells;i++)
1691         {
1692           if(!isFetched[i])
1693             {
1694               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1695               std::vector<int> v,v2;
1696               if(connOfNode!=connPtr+connIPtr[i+1])
1697                 {
1698                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1699                   connOfNode++;
1700                 }
1701               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1702                 if(*connOfNode>=0)
1703                   {
1704                     v=v2;
1705                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1706                     v2.resize(std::distance(v2.begin(),it));
1707                   }
1708               if(v2.size()>1)
1709                 {
1710                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1711                     {
1712                       int pos=commonCellsI->back();
1713                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1714                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1715                         isFetched[*it]=true;
1716                     }
1717                 }
1718             }
1719         }
1720     }
1721   commonCellsArr=commonCells.retn();
1722   commonCellsIArr=commonCellsI.retn();
1723 }
1724
1725 /*!
1726  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1727  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1728  * than \a this->getNumberOfCells() in the returned array means that there is no
1729  * corresponding cell in \a this mesh.
1730  * It is expected that \a this and \a other meshes share the same node coordinates
1731  * array, if it is not so an exception is thrown. 
1732  *  \param [in] other - the mesh to compare with.
1733  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1734  *         valid values [0,1,2], see zipConnectivityTraducer().
1735  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1736  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1737  *         values. The caller is to delete this array using
1738  *         decrRef() as it is no more needed.
1739  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1740  *         mesh.
1741  *
1742  *  \if ENABLE_EXAMPLES
1743  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1744  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1745  *  \endif
1746  *  \sa checkDeepEquivalOnSameNodesWith()
1747  *  \sa checkGeoEquivalWith()
1748  */
1749 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1750 {
1751   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1752   int nbOfCells=getNumberOfCells();
1753   static const int possibleCompType[]={0,1,2};
1754   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1755     {
1756       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1757       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1758       oss << " !";
1759       throw INTERP_KERNEL::Exception(oss.str());
1760     }
1761   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1762   arr=o2n->subArray(nbOfCells);
1763   arr->setName(other->getName());
1764   int tmp;
1765   if(other->getNumberOfCells()==0)
1766     return true;
1767   return arr->getMaxValue(tmp)<nbOfCells;
1768 }
1769
1770 /*!
1771  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1772  * This method tries to determine if \b other is fully included in \b this.
1773  * The main difference is that this method is not expected to throw exception.
1774  * This method has two outputs :
1775  *
1776  * \param other other mesh
1777  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1778  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1779  */
1780 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1781 {
1782   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1783   DataArrayInt *commonCells=0,*commonCellsI=0;
1784   int thisNbCells=getNumberOfCells();
1785   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1786   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1787   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1788   int otherNbCells=other->getNumberOfCells();
1789   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1790   arr2->alloc(otherNbCells,1);
1791   arr2->fillWithZero();
1792   int *arr2Ptr=arr2->getPointer();
1793   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1794   for(int i=0;i<nbOfCommon;i++)
1795     {
1796       int start=commonCellsPtr[commonCellsIPtr[i]];
1797       if(start<thisNbCells)
1798         {
1799           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1800             {
1801               int sig=commonCellsPtr[j]>0?1:-1;
1802               int val=std::abs(commonCellsPtr[j])-1;
1803               if(val>=thisNbCells)
1804                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1805             }
1806         }
1807     }
1808   arr2->setName(other->getName());
1809   if(arr2->presenceOfValue(0))
1810     return false;
1811   arr=arr2.retn();
1812   return true;
1813 }
1814
1815 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1816 {
1817   if(!other)
1818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1819   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1820   if(!otherC)
1821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1822   std::vector<const MEDCouplingUMesh *> ms(2);
1823   ms[0]=this;
1824   ms[1]=otherC;
1825   return MergeUMeshesOnSameCoords(ms);
1826 }
1827
1828 /*!
1829  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1830  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1831  * cellIds is not given explicitely but by a range python like.
1832  * 
1833  * \param start
1834  * \param end
1835  * \param step
1836  * \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.
1837  * \return a newly allocated
1838  * 
1839  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1840  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1841  */
1842 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
1843 {
1844   if(getMeshDimension()!=-1)
1845     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
1846   else
1847     {
1848       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
1849       if(newNbOfCells!=1)
1850         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1851       if(start!=0)
1852         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1853       incrRef();
1854       return const_cast<MEDCouplingUMesh *>(this);
1855     }
1856 }
1857
1858 /*!
1859  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1860  * The result mesh shares or not the node coordinates array with \a this mesh depending
1861  * on \a keepCoords parameter.
1862  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1863  *           to write this mesh to the MED file, its cells must be sorted using
1864  *           sortCellsInMEDFileFrmt().
1865  *  \param [in] begin - an array of cell ids to include to the new mesh.
1866  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1867  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1868  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1869  *         by calling zipCoords().
1870  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
1871  *         to delete this mesh using decrRef() as it is no more needed. 
1872  *  \throw If the coordinates array is not set.
1873  *  \throw If the nodal connectivity of cells is not defined.
1874  *  \throw If any cell id in the array \a begin is not valid.
1875  *
1876  *  \if ENABLE_EXAMPLES
1877  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1878  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1879  *  \endif
1880  */
1881 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1882 {
1883   if(getMeshDimension()!=-1)
1884     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
1885   else
1886     {
1887       if(end-begin!=1)
1888         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1889       if(begin[0]!=0)
1890         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1891       incrRef();
1892       return const_cast<MEDCouplingUMesh *>(this);
1893     }
1894 }
1895
1896 /*!
1897  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1898  *
1899  * 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.
1900  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1901  * The number of cells of \b this will remain the same with this method.
1902  *
1903  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
1904  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
1905  * \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 ).
1906  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1907  */
1908 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1909 {
1910   checkConnectivityFullyDefined();
1911   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1912   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1913     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1914   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1915     {
1916       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1917       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1918       throw INTERP_KERNEL::Exception(oss.str());
1919     }
1920   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1921   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1922     {
1923       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1924       throw INTERP_KERNEL::Exception(oss.str());
1925     }
1926   int nbOfCells=getNumberOfCells();
1927   bool easyAssign=true;
1928   const int *connI=_nodal_connec_index->getConstPointer();
1929   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1930   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1931     {
1932       if(*it>=0 && *it<nbOfCells)
1933         {
1934           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1935         }
1936       else
1937         {
1938           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1939           throw INTERP_KERNEL::Exception(oss.str());
1940         }
1941     }
1942   if(easyAssign)
1943     {
1944       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1945       computeTypes();
1946     }
1947   else
1948     {
1949       DataArrayInt *arrOut=0,*arrIOut=0;
1950       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1951                                                arrOut,arrIOut);
1952       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1953       setConnectivity(arrOut,arrIOut,true);
1954     }
1955 }
1956
1957 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1958 {
1959   checkConnectivityFullyDefined();
1960   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1961   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1963   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1964     {
1965       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1966       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1967       throw INTERP_KERNEL::Exception(oss.str());
1968     }
1969   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
1970   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1971     {
1972       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1973       throw INTERP_KERNEL::Exception(oss.str());
1974     }
1975   int nbOfCells=getNumberOfCells();
1976   bool easyAssign=true;
1977   const int *connI=_nodal_connec_index->getConstPointer();
1978   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1979   int it=start;
1980   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1981     {
1982       if(it>=0 && it<nbOfCells)
1983         {
1984           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1985         }
1986       else
1987         {
1988           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1989           throw INTERP_KERNEL::Exception(oss.str());
1990         }
1991     }
1992   if(easyAssign)
1993     {
1994       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1995       computeTypes();
1996     }
1997   else
1998     {
1999       DataArrayInt *arrOut=0,*arrIOut=0;
2000       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2001                                                 arrOut,arrIOut);
2002       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2003       setConnectivity(arrOut,arrIOut,true);
2004     }
2005 }                      
2006
2007
2008 /*!
2009  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2010  * this->getMeshDimension(), that bound some cells of \a this mesh.
2011  * The cells of lower dimension to include to the result mesh are selected basing on
2012  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2013  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2014  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2015  * created mesh shares the node coordinates array with \a this mesh. 
2016  *  \param [in] begin - the array of node ids.
2017  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2018  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2019  *         array \a begin are added, else cells whose any node is in the
2020  *         array \a begin are added.
2021  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2022  *         to delete this mesh using decrRef() as it is no more needed. 
2023  *  \throw If the coordinates array is not set.
2024  *  \throw If the nodal connectivity of cells is not defined.
2025  *  \throw If any node id in \a begin is not valid.
2026  *
2027  *  \if ENABLE_EXAMPLES
2028  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2029  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2030  *  \endif
2031  */
2032 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2033 {
2034   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2035   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2036   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2037   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2038   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2039 }
2040
2041 /*!
2042  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2043  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2044  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2045  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2046  *         by calling zipCoords().
2047  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2048  *         to delete this mesh using decrRef() as it is no more needed. 
2049  *  \throw If the coordinates array is not set.
2050  *  \throw If the nodal connectivity of cells is not defined.
2051  *
2052  *  \if ENABLE_EXAMPLES
2053  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2054  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2055  *  \endif
2056  */
2057 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2058 {
2059   DataArrayInt *desc=DataArrayInt::New();
2060   DataArrayInt *descIndx=DataArrayInt::New();
2061   DataArrayInt *revDesc=DataArrayInt::New();
2062   DataArrayInt *revDescIndx=DataArrayInt::New();
2063   //
2064   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2065   revDesc->decrRef();
2066   desc->decrRef();
2067   descIndx->decrRef();
2068   int nbOfCells=meshDM1->getNumberOfCells();
2069   const int *revDescIndxC=revDescIndx->getConstPointer();
2070   std::vector<int> boundaryCells;
2071   for(int i=0;i<nbOfCells;i++)
2072     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2073       boundaryCells.push_back(i);
2074   revDescIndx->decrRef();
2075   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2076   return ret;
2077 }
2078
2079 /*!
2080  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2081  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2082  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2083  */
2084 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2085 {
2086   checkFullyDefined();
2087   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2088   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2089   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2090   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2091   //
2092   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2093   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2094   //
2095   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2096   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2097   const int *revDescPtr=revDesc->getConstPointer();
2098   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2099   int nbOfCells=getNumberOfCells();
2100   std::vector<bool> ret1(nbOfCells,false);
2101   int sz=0;
2102   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2103     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2104       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2105   //
2106   DataArrayInt *ret2=DataArrayInt::New();
2107   ret2->alloc(sz,1);
2108   int *ret2Ptr=ret2->getPointer();
2109   sz=0;
2110   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2111     if(*it)
2112       *ret2Ptr++=sz;
2113   ret2->setName("BoundaryCells");
2114   return ret2;
2115 }
2116
2117 /*!
2118  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2119  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2120  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2121  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2122  *
2123  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2124  * 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
2125  * equals a cell in \b otherDimM1OnSameCoords.
2126  *
2127  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2128  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2129  *
2130  * \param [in] otherDimM1OnSameCoords
2131  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2132  * \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
2133  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2134  */
2135 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2136 {
2137   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2138     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2139   checkConnectivityFullyDefined();
2140   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2141   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2143   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2144   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2145   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2146   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2147   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2148   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2149   DataArrayInt *idsOtherInConsti=0;
2150   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2151   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2152   if(!b)
2153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2154   std::set<int> s1;
2155   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2156     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2157   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2158   s1arr_renum1->sort();
2159   cellIdsRk0=s0arr.retn();
2160   //cellIdsRk1=s_renum1.retn();
2161   cellIdsRk1=s1arr_renum1.retn();
2162 }
2163
2164 /*!
2165  * 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
2166  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2167  * 
2168  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2169  */
2170 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2171 {
2172   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2173   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2174   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2175   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2176   //
2177   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2178   revDesc=0; desc=0; descIndx=0;
2179   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2180   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2181   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2182 }
2183
2184 /*!
2185  * Finds nodes lying on the boundary of \a this mesh.
2186  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2187  *          nodes. The caller is to delete this array using decrRef() as it is no
2188  *          more needed.
2189  *  \throw If the coordinates array is not set.
2190  *  \throw If the nodal connectivity of cells is node defined.
2191  *
2192  *  \if ENABLE_EXAMPLES
2193  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2194  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2195  *  \endif
2196  */
2197 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2198 {
2199   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2200   return skin->computeFetchedNodeIds();
2201 }
2202
2203 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2204 {
2205   incrRef();
2206   return const_cast<MEDCouplingUMesh *>(this);
2207 }
2208
2209 /*!
2210  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2211  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2212  * 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.
2213  * 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.
2214  * 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.
2215  *
2216  * \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
2217  *             parameter is altered during the call.
2218  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2219  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2220  * \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.
2221  *
2222  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2223  */
2224 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2225                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2226 {
2227   typedef MCAuto<DataArrayInt> DAInt;
2228   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2229
2230   checkFullyDefined();
2231   otherDimM1OnSameCoords.checkFullyDefined();
2232   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2233     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2234   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2235     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2236
2237   // Checking star-shaped M1 group:
2238   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2239   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2240   DAInt dsi = rdit0->deltaShiftIndex();
2241   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2242   if(idsTmp0->getNumberOfTuples())
2243     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2244   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2245
2246   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2247   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2248   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2249   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2250   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2251   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2252   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2253   dsi = rdit0->deltaShiftIndex();
2254   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2255   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2256   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2257   // In 3D, some points on the boundary of M0 still need duplication:
2258   DAInt notDup = 0;
2259   if (getMeshDimension() == 3)
2260     {
2261       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2262       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2263       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2264       DataArrayInt * corresp=0;
2265       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2266       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2267       corresp->decrRef();
2268       if (validIds->getNumberOfTuples())
2269         {
2270           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2271           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2272           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2273           notDup = xtrem->buildSubstraction(fNodes1);
2274         }
2275       else
2276         notDup = xtrem->buildSubstraction(fNodes);
2277     }
2278   else
2279     notDup = xtrem->buildSubstraction(fNodes);
2280
2281   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2282   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2283   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2284   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2285
2286   //
2287   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2288   int nCells2 = m0Part2->getNumberOfCells();
2289   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2290   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2291
2292   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2293   DataArrayInt *tmp00=0,*tmp11=0;
2294   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2295   DAInt neighInit00(tmp00);
2296   DAInt neighIInit00(tmp11);
2297   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2298   DataArrayInt *idsTmp=0;
2299   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2300   DAInt ids(idsTmp);
2301   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2302   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2303   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2304   DataArrayInt *tmp0=0,*tmp1=0;
2305   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2306   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2307   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2308   DAInt neigh00(tmp0);
2309   DAInt neighI00(tmp1);
2310
2311   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2312   int seed = 0, nIter = 0;
2313   int nIterMax = nCells2+1; // Safety net for the loop
2314   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2315   hitCells->fillWithValue(-1);
2316   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2317   cellsToModifyConn0_torenum->alloc(0,1);
2318   while (nIter < nIterMax)
2319     {
2320       DAInt t = hitCells->findIdsEqual(-1);
2321       if (!t->getNumberOfTuples())
2322         break;
2323       // Connex zone without the crack (to compute the next seed really)
2324       int dnu;
2325       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2326       int cnt = 0;
2327       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2328         hitCells->setIJ(*ptr,0,1);
2329       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2330       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2331       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2332       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2333       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2334       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2335       DAInt intersec = nonHitCells->buildIntersection(comple);
2336       if (intersec->getNumberOfTuples())
2337         { seed = intersec->getIJ(0,0); }
2338       else
2339         { break; }
2340       nIter++;
2341     }
2342   if (nIter >= nIterMax)
2343     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2344
2345   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2346   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2347   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2348   //
2349   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2350   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2351   nodeIdsToDuplicate=dupl.retn();
2352 }
2353
2354 /*!
2355  * This method operates a modification of the connectivity and coords in \b this.
2356  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2357  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2358  * 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
2359  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2360  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2361  * 
2362  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2363  * 
2364  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2365  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2366  */
2367 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2368 {
2369   int nbOfNodes=getNumberOfNodes();
2370   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2371   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2372 }
2373
2374 /*!
2375  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2376  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2377  *
2378  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2379  *
2380  * \sa renumberNodesInConn
2381  */
2382 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2383 {
2384   checkConnectivityFullyDefined();
2385   int *conn(getNodalConnectivity()->getPointer());
2386   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2387   int nbOfCells(getNumberOfCells());
2388   for(int i=0;i<nbOfCells;i++)
2389     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2390       {
2391         int& node=conn[iconn];
2392         if(node>=0)//avoid polyhedron separator
2393           {
2394             node+=offset;
2395           }
2396       }
2397   _nodal_connec->declareAsNew();
2398   updateTime();
2399 }
2400
2401 /*!
2402  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2403  *  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
2404  *  of a big mesh.
2405  */
2406 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2407 {
2408   checkConnectivityFullyDefined();
2409   int *conn(getNodalConnectivity()->getPointer());
2410   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2411   int nbOfCells(getNumberOfCells());
2412   for(int i=0;i<nbOfCells;i++)
2413     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2414       {
2415         int& node=conn[iconn];
2416         if(node>=0)//avoid polyhedron separator
2417           {
2418             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2419             if(it!=newNodeNumbersO2N.end())
2420               {
2421                 node=(*it).second;
2422               }
2423             else
2424               {
2425                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2426                 throw INTERP_KERNEL::Exception(oss.str());
2427               }
2428           }
2429       }
2430   _nodal_connec->declareAsNew();
2431   updateTime();
2432 }
2433
2434 /*!
2435  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2436  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2437  * This method is a generalization of shiftNodeNumbersInConn().
2438  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2439  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2440  *         this->getNumberOfNodes(), in "Old to New" mode. 
2441  *         See \ref numbering for more info on renumbering modes.
2442  *  \throw If the nodal connectivity of cells is not defined.
2443  *
2444  *  \if ENABLE_EXAMPLES
2445  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2446  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2447  *  \endif
2448  */
2449 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2450 {
2451   checkConnectivityFullyDefined();
2452   int *conn=getNodalConnectivity()->getPointer();
2453   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2454   int nbOfCells(getNumberOfCells());
2455   for(int i=0;i<nbOfCells;i++)
2456     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2457       {
2458         int& node=conn[iconn];
2459         if(node>=0)//avoid polyhedron separator
2460           {
2461             node=newNodeNumbersO2N[node];
2462           }
2463       }
2464   _nodal_connec->declareAsNew();
2465   updateTime();
2466 }
2467
2468 /*!
2469  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2470  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2471  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2472  * 
2473  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2474  */
2475 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2476 {
2477   checkConnectivityFullyDefined();
2478   int *conn=getNodalConnectivity()->getPointer();
2479   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2480   int nbOfCells=getNumberOfCells();
2481   for(int i=0;i<nbOfCells;i++)
2482     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2483       {
2484         int& node=conn[iconn];
2485         if(node>=0)//avoid polyhedron separator
2486           {
2487             node+=delta;
2488           }
2489       }
2490   _nodal_connec->declareAsNew();
2491   updateTime();
2492 }
2493
2494 /*!
2495  * This method operates a modification of the connectivity in \b this.
2496  * 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.
2497  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2498  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2499  * 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
2500  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2501  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2502  * 
2503  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2504  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2505  * 
2506  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2507  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2508  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2509  */
2510 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2511 {
2512   checkConnectivityFullyDefined();
2513   std::map<int,int> m;
2514   int val=offset;
2515   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2516     m[*work]=val;
2517   int *conn=getNodalConnectivity()->getPointer();
2518   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2519   int nbOfCells=getNumberOfCells();
2520   for(int i=0;i<nbOfCells;i++)
2521     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2522       {
2523         int& node=conn[iconn];
2524         if(node>=0)//avoid polyhedron separator
2525           {
2526             std::map<int,int>::iterator it=m.find(node);
2527             if(it!=m.end())
2528               node=(*it).second;
2529           }
2530       }
2531   updateTime();
2532 }
2533
2534 /*!
2535  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2536  *
2537  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2538  * After the call of this method the number of cells remains the same as before.
2539  *
2540  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2541  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2542  * be strictly in [0;this->getNumberOfCells()).
2543  *
2544  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2545  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2546  * should be contained in[0;this->getNumberOfCells()).
2547  * 
2548  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2549  * \param check
2550  */
2551 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2552 {
2553   checkConnectivityFullyDefined();
2554   int nbCells=getNumberOfCells();
2555   const int *array=old2NewBg;
2556   if(check)
2557     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2558   //
2559   const int *conn=_nodal_connec->getConstPointer();
2560   const int *connI=_nodal_connec_index->getConstPointer();
2561   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2562   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2563   const int *n2oPtr=n2o->begin();
2564   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2565   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2566   newConn->copyStringInfoFrom(*_nodal_connec);
2567   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2568   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2569   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2570   //
2571   int *newC=newConn->getPointer();
2572   int *newCI=newConnI->getPointer();
2573   int loc=0;
2574   newCI[0]=loc;
2575   for(int i=0;i<nbCells;i++)
2576     {
2577       int pos=n2oPtr[i];
2578       int nbOfElts=connI[pos+1]-connI[pos];
2579       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2580       loc+=nbOfElts;
2581       newCI[i+1]=loc;
2582     }
2583   //
2584   setConnectivity(newConn,newConnI);
2585   if(check)
2586     free(const_cast<int *>(array));
2587 }
2588
2589 /*!
2590  * Finds cells whose bounding boxes intersect a given bounding box.
2591  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2592  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2593  *         zMax (if in 3D). 
2594  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2595  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2596  *         extent of the bounding box of cell to produce an addition to this bounding box.
2597  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2598  *         cells. The caller is to delete this array using decrRef() as it is no more
2599  *         needed. 
2600  *  \throw If the coordinates array is not set.
2601  *  \throw If the nodal connectivity of cells is not defined.
2602  *
2603  *  \if ENABLE_EXAMPLES
2604  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2605  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2606  *  \endif
2607  */
2608 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2609 {
2610   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2611   if(getMeshDimension()==-1)
2612     {
2613       elems->pushBackSilent(0);
2614       return elems.retn();
2615     }
2616   int dim=getSpaceDimension();
2617   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2618   const int* conn      = getNodalConnectivity()->getConstPointer();
2619   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2620   const double* coords = getCoords()->getConstPointer();
2621   int nbOfCells=getNumberOfCells();
2622   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2623     {
2624       for (int i=0; i<dim; i++)
2625         {
2626           elem_bb[i*2]=std::numeric_limits<double>::max();
2627           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2628         }
2629
2630       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2631         {
2632           int node= conn[inode];
2633           if(node>=0)//avoid polyhedron separator
2634             {
2635               for (int idim=0; idim<dim; idim++)
2636                 {
2637                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2638                     {
2639                       elem_bb[idim*2] = coords[node*dim+idim] ;
2640                     }
2641                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2642                     {
2643                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2644                     }
2645                 }
2646             }
2647         }
2648       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2649         elems->pushBackSilent(ielem);
2650     }
2651   return elems.retn();
2652 }
2653
2654 /*!
2655  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2656  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2657  * added in 'elems' parameter.
2658  */
2659 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2660 {
2661   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2662   if(getMeshDimension()==-1)
2663     {
2664       elems->pushBackSilent(0);
2665       return elems.retn();
2666     }
2667   int dim=getSpaceDimension();
2668   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2669   const int* conn      = getNodalConnectivity()->getConstPointer();
2670   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2671   const double* coords = getCoords()->getConstPointer();
2672   int nbOfCells=getNumberOfCells();
2673   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2674     {
2675       for (int i=0; i<dim; i++)
2676         {
2677           elem_bb[i*2]=std::numeric_limits<double>::max();
2678           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2679         }
2680
2681       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2682         {
2683           int node= conn[inode];
2684           if(node>=0)//avoid polyhedron separator
2685             {
2686               for (int idim=0; idim<dim; idim++)
2687                 {
2688                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2689                     {
2690                       elem_bb[idim*2] = coords[node*dim+idim] ;
2691                     }
2692                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2693                     {
2694                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2695                     }
2696                 }
2697             }
2698         }
2699       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2700         elems->pushBackSilent(ielem);
2701     }
2702   return elems.retn();
2703 }
2704
2705 /*!
2706  * Returns a type of a cell by its id.
2707  *  \param [in] cellId - the id of the cell of interest.
2708  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2709  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2710  */
2711 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2712 {
2713   const int *ptI=_nodal_connec_index->getConstPointer();
2714   const int *pt=_nodal_connec->getConstPointer();
2715   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2716     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2717   else
2718     {
2719       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2720       throw INTERP_KERNEL::Exception(oss.str());
2721     }
2722 }
2723
2724 /*!
2725  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2726  * This method does not throw exception if geometric type \a type is not in \a this.
2727  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2728  * The coordinates array is not considered here.
2729  *
2730  * \param [in] type the geometric type
2731  * \return cell ids in this having geometric type \a type.
2732  */
2733 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2734 {
2735
2736   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2737   ret->alloc(0,1);
2738   checkConnectivityFullyDefined();
2739   int nbCells=getNumberOfCells();
2740   int mdim=getMeshDimension();
2741   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2742   if(mdim!=(int)cm.getDimension())
2743     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2744   const int *ptI=_nodal_connec_index->getConstPointer();
2745   const int *pt=_nodal_connec->getConstPointer();
2746   for(int i=0;i<nbCells;i++)
2747     {
2748       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2749         ret->pushBackSilent(i);
2750     }
2751   return ret.retn();
2752 }
2753
2754 /*!
2755  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2756  */
2757 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2758 {
2759   const int *ptI=_nodal_connec_index->getConstPointer();
2760   const int *pt=_nodal_connec->getConstPointer();
2761   int nbOfCells=getNumberOfCells();
2762   int ret=0;
2763   for(int i=0;i<nbOfCells;i++)
2764     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2765       ret++;
2766   return ret;
2767 }
2768
2769 /*!
2770  * Returns the nodal connectivity of a given cell.
2771  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2772  * all returned node ids can be used in getCoordinatesOfNode().
2773  *  \param [in] cellId - an id of the cell of interest.
2774  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2775  *         cleared before the appending.
2776  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2777  */
2778 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2779 {
2780   const int *ptI=_nodal_connec_index->getConstPointer();
2781   const int *pt=_nodal_connec->getConstPointer();
2782   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2783     if(*w>=0)
2784       conn.push_back(*w);
2785 }
2786
2787 std::string MEDCouplingUMesh::simpleRepr() const
2788 {
2789   static const char msg0[]="No coordinates specified !";
2790   std::ostringstream ret;
2791   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2792   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2793   int tmpp1,tmpp2;
2794   double tt=getTime(tmpp1,tmpp2);
2795   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2796   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2797   if(_mesh_dim>=-1)
2798     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2799   else
2800     { ret << " Mesh dimension has not been set or is invalid !"; }
2801   if(_coords!=0)
2802     {
2803       const int spaceDim=getSpaceDimension();
2804       ret << spaceDim << "\nInfo attached on space dimension : ";
2805       for(int i=0;i<spaceDim;i++)
2806         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2807       ret << "\n";
2808     }
2809   else
2810     ret << msg0 << "\n";
2811   ret << "Number of nodes : ";
2812   if(_coords!=0)
2813     ret << getNumberOfNodes() << "\n";
2814   else
2815     ret << msg0 << "\n";
2816   ret << "Number of cells : ";
2817   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2818     ret << getNumberOfCells() << "\n";
2819   else
2820     ret << "No connectivity specified !" << "\n";
2821   ret << "Cell types present : ";
2822   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2823     {
2824       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2825       ret << cm.getRepr() << " ";
2826     }
2827   ret << "\n";
2828   return ret.str();
2829 }
2830
2831 std::string MEDCouplingUMesh::advancedRepr() const
2832 {
2833   std::ostringstream ret;
2834   ret << simpleRepr();
2835   ret << "\nCoordinates array : \n___________________\n\n";
2836   if(_coords)
2837     _coords->reprWithoutNameStream(ret);
2838   else
2839     ret << "No array set !\n";
2840   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2841   reprConnectivityOfThisLL(ret);
2842   return ret.str();
2843 }
2844
2845 /*!
2846  * This method returns a C++ code that is a dump of \a this.
2847  * This method will throw if this is not fully defined.
2848  */
2849 std::string MEDCouplingUMesh::cppRepr() const
2850 {
2851   static const char coordsName[]="coords";
2852   static const char connName[]="conn";
2853   static const char connIName[]="connI";
2854   checkFullyDefined();
2855   std::ostringstream ret; ret << "// coordinates" << std::endl;
2856   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2857   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2858   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2859   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2860   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2861   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2862   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2863   return ret.str();
2864 }
2865
2866 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2867 {
2868   std::ostringstream ret;
2869   reprConnectivityOfThisLL(ret);
2870   return ret.str();
2871 }
2872
2873 /*!
2874  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2875  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2876  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2877  * some algos).
2878  * 
2879  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2880  * 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
2881  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2882  */
2883 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2884 {
2885   int mdim=getMeshDimension();
2886   if(mdim<0)
2887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2888   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2889   MCAuto<DataArrayInt> tmp1,tmp2;
2890   bool needToCpyCT=true;
2891   if(!_nodal_connec)
2892     {
2893       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2894       needToCpyCT=false;
2895     }
2896   else
2897     {
2898       tmp1=_nodal_connec;
2899       tmp1->incrRef();
2900     }
2901   if(!_nodal_connec_index)
2902     {
2903       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2904       needToCpyCT=false;
2905     }
2906   else
2907     {
2908       tmp2=_nodal_connec_index;
2909       tmp2->incrRef();
2910     }
2911   ret->setConnectivity(tmp1,tmp2,false);
2912   if(needToCpyCT)
2913     ret->_types=_types;
2914   if(!_coords)
2915     {
2916       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2917       ret->setCoords(coords);
2918     }
2919   else
2920     ret->setCoords(_coords);
2921   return ret.retn();
2922 }
2923
2924 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2925 {
2926   const int *ptI=_nodal_connec_index->getConstPointer();
2927   const int *pt=_nodal_connec->getConstPointer();
2928   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2929     return ptI[cellId+1]-ptI[cellId]-1;
2930   else
2931     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2932 }
2933
2934 /*!
2935  * Returns types of cells of the specified part of \a this mesh.
2936  * This method avoids computing sub-mesh explicitely to get its types.
2937  *  \param [in] begin - an array of cell ids of interest.
2938  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2939  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2940  *         describing the cell types. 
2941  *  \throw If the coordinates array is not set.
2942  *  \throw If the nodal connectivity of cells is not defined.
2943  *  \sa getAllGeoTypes()
2944  */
2945 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2946 {
2947   checkFullyDefined();
2948   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2949   const int *conn=_nodal_connec->getConstPointer();
2950   const int *connIndex=_nodal_connec_index->getConstPointer();
2951   for(const int *w=begin;w!=end;w++)
2952     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2953   return ret;
2954 }
2955
2956 /*!
2957  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
2958  * Optionally updates
2959  * a set of types of cells constituting \a this mesh. 
2960  * This method is for advanced users having prepared their connectivity before. For
2961  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2962  *  \param [in] conn - the nodal connectivity array. 
2963  *  \param [in] connIndex - the nodal connectivity index array.
2964  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2965  *         mesh is updated.
2966  */
2967 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2968 {
2969   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2970   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2971   if(isComputingTypes)
2972     computeTypes();
2973   declareAsNew();
2974 }
2975
2976 /*!
2977  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
2978  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2979  */
2980 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2981     _nodal_connec(0),_nodal_connec_index(0),
2982     _types(other._types)
2983 {
2984   if(other._nodal_connec)
2985     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
2986   if(other._nodal_connec_index)
2987     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
2988 }
2989
2990 MEDCouplingUMesh::~MEDCouplingUMesh()
2991 {
2992   if(_nodal_connec)
2993     _nodal_connec->decrRef();
2994   if(_nodal_connec_index)
2995     _nodal_connec_index->decrRef();
2996 }
2997
2998 /*!
2999  * Recomputes a set of cell types of \a this mesh. For more info see
3000  * \ref MEDCouplingUMeshNodalConnectivity.
3001  */
3002 void MEDCouplingUMesh::computeTypes()
3003 {
3004   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3005 }
3006
3007
3008 /*!
3009  * Returns a number of cells constituting \a this mesh. 
3010  *  \return int - the number of cells in \a this mesh.
3011  *  \throw If the nodal connectivity of cells is not defined.
3012  */
3013 int MEDCouplingUMesh::getNumberOfCells() const
3014
3015   if(_nodal_connec_index)
3016     return _nodal_connec_index->getNumberOfTuples()-1;
3017   else
3018     if(_mesh_dim==-1)
3019       return 1;
3020     else
3021       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3022 }
3023
3024 /*!
3025  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3026  * mesh. For more info see \ref meshes.
3027  *  \return int - the dimension of \a this mesh.
3028  *  \throw If the mesh dimension is not defined using setMeshDimension().
3029  */
3030 int MEDCouplingUMesh::getMeshDimension() const
3031 {
3032   if(_mesh_dim<-1)
3033     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3034   return _mesh_dim;
3035 }
3036
3037 /*!
3038  * Returns a length of the nodal connectivity array.
3039  * This method is for test reason. Normally the integer returned is not useable by
3040  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3041  *  \return int - the length of the nodal connectivity array.
3042  */
3043 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3044 {
3045   return _nodal_connec->getNbOfElems();
3046 }
3047
3048 /*!
3049  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3050  */
3051 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3052 {
3053   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3054   tinyInfo.push_back(getMeshDimension());
3055   tinyInfo.push_back(getNumberOfCells());
3056   if(_nodal_connec)
3057     tinyInfo.push_back(getNodalConnectivityArrayLen());
3058   else
3059     tinyInfo.push_back(-1);
3060 }
3061
3062 /*!
3063  * First step of unserialization process.
3064  */
3065 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3066 {
3067   return tinyInfo[6]<=0;
3068 }
3069
3070 /*!
3071  * Second step of serialization process.
3072  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3073  * \param a1
3074  * \param a2
3075  * \param littleStrings
3076  */
3077 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3078 {
3079   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3080   if(tinyInfo[5]!=-1)
3081     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3082 }
3083
3084 /*!
3085  * Third and final step of serialization process.
3086  */
3087 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3088 {
3089   MEDCouplingPointSet::serialize(a1,a2);
3090   if(getMeshDimension()>-1)
3091     {
3092       a1=DataArrayInt::New();
3093       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3094       int *ptA1=a1->getPointer();
3095       const int *conn=getNodalConnectivity()->getConstPointer();
3096       const int *index=getNodalConnectivityIndex()->getConstPointer();
3097       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3098       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3099     }
3100   else
3101     a1=0;
3102 }
3103
3104 /*!
3105  * Second and final unserialization process.
3106  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3107  */
3108 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3109 {
3110   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3111   setMeshDimension(tinyInfo[5]);
3112   if(tinyInfo[7]!=-1)
3113     {
3114       // Connectivity
3115       const int *recvBuffer=a1->getConstPointer();
3116       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3117       myConnecIndex->alloc(tinyInfo[6]+1,1);
3118       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3119       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3120       myConnec->alloc(tinyInfo[7],1);
3121       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3122       setConnectivity(myConnec, myConnecIndex);
3123     }
3124 }
3125
3126
3127
3128 /*!
3129  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3130  * mesh.<br>
3131  * For 1D cells, the returned field contains lengths.<br>
3132  * For 2D cells, the returned field contains areas.<br>
3133  * For 3D cells, the returned field contains volumes.
3134  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3135  *         orientation, i.e. the volume is always positive.
3136  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3137  *         and one time . The caller is to delete this field using decrRef() as it is no
3138  *         more needed.
3139  */
3140 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3141 {
3142   std::string name="MeasureOfMesh_";
3143   name+=getName();
3144   int nbelem=getNumberOfCells();
3145   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3146   field->setName(name);
3147   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3148   array->alloc(nbelem,1);
3149   double *area_vol=array->getPointer();
3150   field->setArray(array) ; array=0;
3151   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3152   field->synchronizeTimeWithMesh();
3153   if(getMeshDimension()!=-1)
3154     {
3155       int ipt;
3156       INTERP_KERNEL::NormalizedCellType type;
3157       int dim_space=getSpaceDimension();
3158       const double *coords=getCoords()->getConstPointer();
3159       const int *connec=getNodalConnectivity()->getConstPointer();
3160       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3161       for(int iel=0;iel<nbelem;iel++)
3162         {
3163           ipt=connec_index[iel];
3164           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3165           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);
3166         }
3167       if(isAbs)
3168         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3169     }
3170   else
3171     {
3172       area_vol[0]=std::numeric_limits<double>::max();
3173     }
3174   return field.retn();
3175 }
3176
3177 /*!
3178  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3179  * mesh.<br>
3180  * For 1D cells, the returned array contains lengths.<br>
3181  * For 2D cells, the returned array contains areas.<br>
3182  * For 3D cells, the returned array contains volumes.
3183  * This method avoids building explicitly a part of \a this mesh to perform the work.
3184  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3185  *         orientation, i.e. the volume is always positive.
3186  *  \param [in] begin - an array of cell ids of interest.
3187  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3188  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3189  *          delete this array using decrRef() as it is no more needed.
3190  * 
3191  *  \if ENABLE_EXAMPLES
3192  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3193  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3194  *  \endif
3195  *  \sa getMeasureField()
3196  */
3197 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3198 {
3199   std::string name="PartMeasureOfMesh_";
3200   name+=getName();
3201   int nbelem=(int)std::distance(begin,end);
3202   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3203   array->setName(name);
3204   array->alloc(nbelem,1);
3205   double *area_vol=array->getPointer();
3206   if(getMeshDimension()!=-1)
3207     {
3208       int ipt;
3209       INTERP_KERNEL::NormalizedCellType type;
3210       int dim_space=getSpaceDimension();
3211       const double *coords=getCoords()->getConstPointer();
3212       const int *connec=getNodalConnectivity()->getConstPointer();
3213       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3214       for(const int *iel=begin;iel!=end;iel++)
3215         {
3216           ipt=connec_index[*iel];
3217           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3218           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3219         }
3220       if(isAbs)
3221         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3222     }
3223   else
3224     {
3225       area_vol[0]=std::numeric_limits<double>::max();
3226     }
3227   return array.retn();
3228 }
3229
3230 /*!
3231  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3232  * \a this one. The returned field contains the dual cell volume for each corresponding
3233  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3234  *  the dual mesh in P1 sens of \a this.<br>
3235  * For 1D cells, the returned field contains lengths.<br>
3236  * For 2D cells, the returned field contains areas.<br>
3237  * For 3D cells, the returned field contains volumes.
3238  * This method is useful to check "P1*" conservative interpolators.
3239  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3240  *         orientation, i.e. the volume is always positive.
3241  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3242  *          nodes and one time. The caller is to delete this array using decrRef() as
3243  *          it is no more needed.
3244  */
3245 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3246 {
3247   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3248   std::string name="MeasureOnNodeOfMesh_";
3249   name+=getName();
3250   int nbNodes=getNumberOfNodes();
3251   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3252   double cst=1./((double)getMeshDimension()+1.);
3253   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3254   array->alloc(nbNodes,1);
3255   double *valsToFill=array->getPointer();
3256   std::fill(valsToFill,valsToFill+nbNodes,0.);
3257   const double *values=tmp->getArray()->getConstPointer();
3258   MCAuto<DataArrayInt> da=DataArrayInt::New();
3259   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3260   getReverseNodalConnectivity(da,daInd);
3261   const int *daPtr=da->getConstPointer();
3262   const int *daIPtr=daInd->getConstPointer();
3263   for(int i=0;i<nbNodes;i++)
3264     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3265       valsToFill[i]+=cst*values[*cell];
3266   ret->setMesh(this);
3267   ret->setArray(array);
3268   return ret.retn();
3269 }
3270
3271 /*!
3272  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3273  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3274  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3275  * and are normalized.
3276  * <br> \a this can be either 
3277  * - a  2D mesh in 2D or 3D space or 
3278  * - an 1D mesh in 2D space.
3279  * 
3280  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3281  *          cells and one time. The caller is to delete this field using decrRef() as
3282  *          it is no more needed.
3283  *  \throw If the nodal connectivity of cells is not defined.
3284  *  \throw If the coordinates array is not set.
3285  *  \throw If the mesh dimension is not set.
3286  *  \throw If the mesh and space dimension is not as specified above.
3287  */
3288 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3289 {
3290   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3291     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3292   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3293   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3294   int nbOfCells=getNumberOfCells();
3295   int nbComp=getMeshDimension()+1;
3296   array->alloc(nbOfCells,nbComp);
3297   double *vals=array->getPointer();
3298   const int *connI=_nodal_connec_index->getConstPointer();
3299   const int *conn=_nodal_connec->getConstPointer();
3300   const double *coords=_coords->getConstPointer();
3301   if(getMeshDimension()==2)
3302     {
3303       if(getSpaceDimension()==3)
3304         {
3305           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3306           const double *locPtr=loc->getConstPointer();
3307           for(int i=0;i<nbOfCells;i++,vals+=3)
3308             {
3309               int offset=connI[i];
3310               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3311               double n=INTERP_KERNEL::norm<3>(vals);
3312               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3313             }
3314         }
3315       else
3316         {
3317           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3318           const double *isAbsPtr=isAbs->getArray()->begin();
3319           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3320             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3321         }
3322     }
3323   else//meshdimension==1
3324     {
3325       double tmp[2];
3326       for(int i=0;i<nbOfCells;i++)
3327         {
3328           int offset=connI[i];
3329           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3330           double n=INTERP_KERNEL::norm<2>(tmp);
3331           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3332           *vals++=-tmp[1];
3333           *vals++=tmp[0];
3334         }
3335     }
3336   ret->setArray(array);
3337   ret->setMesh(this);
3338   ret->synchronizeTimeWithSupport();
3339   return ret.retn();
3340 }
3341
3342 /*!
3343  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3344  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3345  * and are normalized.
3346  * <br> \a this can be either 
3347  * - a  2D mesh in 2D or 3D space or 
3348  * - an 1D mesh in 2D space.
3349  * 
3350  * This method avoids building explicitly a part of \a this mesh to perform the work.
3351  *  \param [in] begin - an array of cell ids of interest.
3352  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3353  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3354  *          cells and one time. The caller is to delete this field using decrRef() as
3355  *          it is no more needed.
3356  *  \throw If the nodal connectivity of cells is not defined.
3357  *  \throw If the coordinates array is not set.
3358  *  \throw If the mesh dimension is not set.
3359  *  \throw If the mesh and space dimension is not as specified above.
3360  *  \sa buildOrthogonalField()
3361  *
3362  *  \if ENABLE_EXAMPLES
3363  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3364  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3365  *  \endif
3366  */
3367 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3368 {
3369   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3370     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3371   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3372   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3373   std::size_t nbelems=std::distance(begin,end);
3374   int nbComp=getMeshDimension()+1;
3375   array->alloc((int)nbelems,nbComp);
3376   double *vals=array->getPointer();
3377   const int *connI=_nodal_connec_index->getConstPointer();
3378   const int *conn=_nodal_connec->getConstPointer();
3379   const double *coords=_coords->getConstPointer();
3380   if(getMeshDimension()==2)
3381     {
3382       if(getSpaceDimension()==3)
3383         {
3384           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3385           const double *locPtr=loc->getConstPointer();
3386           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3387             {
3388               int offset=connI[*i];
3389               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3390               double n=INTERP_KERNEL::norm<3>(vals);
3391               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3392             }
3393         }
3394       else
3395         {
3396           for(std::size_t i=0;i<nbelems;i++)
3397             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3398         }
3399     }
3400   else//meshdimension==1
3401     {
3402       double tmp[2];
3403       for(const int *i=begin;i!=end;i++)
3404         {
3405           int offset=connI[*i];
3406           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3407           double n=INTERP_KERNEL::norm<2>(tmp);
3408           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3409           *vals++=-tmp[1];
3410           *vals++=tmp[0];
3411         }
3412     }
3413   ret->setArray(array);
3414   ret->setMesh(this);
3415   ret->synchronizeTimeWithSupport();
3416   return ret.retn();
3417 }
3418
3419 /*!
3420  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3421  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3422  * and are \b not normalized.
3423  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3424  *          cells and one time. The caller is to delete this field using decrRef() as
3425  *          it is no more needed.
3426  *  \throw If the nodal connectivity of cells is not defined.
3427  *  \throw If the coordinates array is not set.
3428  *  \throw If \a this->getMeshDimension() != 1.
3429  *  \throw If \a this mesh includes cells of type other than SEG2.
3430  */
3431 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3432 {
3433   if(getMeshDimension()!=1)
3434     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3435   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3436     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3437   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3438   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3439   int nbOfCells=getNumberOfCells();
3440   int spaceDim=getSpaceDimension();
3441   array->alloc(nbOfCells,spaceDim);
3442   double *pt=array->getPointer();
3443   const double *coo=getCoords()->getConstPointer();
3444   std::vector<int> conn;
3445   conn.reserve(2);
3446   for(int i=0;i<nbOfCells;i++)
3447     {
3448       conn.resize(0);
3449       getNodeIdsOfCell(i,conn);
3450       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3451     }
3452   ret->setArray(array);
3453   ret->setMesh(this);
3454   ret->synchronizeTimeWithSupport();
3455   return ret.retn();
3456 }
3457
3458 /*!
3459  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3460  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3461  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3462  * from. If a result face is shared by two 3D cells, then the face in included twice in
3463  * the result mesh.
3464  *  \param [in] origin - 3 components of a point defining location of the plane.
3465  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3466  *         must be greater than 1e-6.
3467  *  \param [in] eps - half-thickness of the plane.
3468  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3469  *         producing correspondent 2D cells. The caller is to delete this array
3470  *         using decrRef() as it is no more needed.
3471  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3472  *         not share the node coordinates array with \a this mesh. The caller is to
3473  *         delete this mesh using decrRef() as it is no more needed.  
3474  *  \throw If the coordinates array is not set.
3475  *  \throw If the nodal connectivity of cells is not defined.
3476  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3477  *  \throw If magnitude of \a vec is less than 1e-6.
3478  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3479  *  \throw If \a this includes quadratic cells.
3480  */
3481 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3482 {
3483   checkFullyDefined();
3484   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3485     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3486   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3487   if(candidates->empty())
3488     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3489   std::vector<int> nodes;
3490   DataArrayInt *cellIds1D=0;
3491   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3492   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3493   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3494   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3495   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3496   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3497   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3498   revDesc2=0; revDescIndx2=0;
3499   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3500   revDesc1=0; revDescIndx1=0;
3501   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3502   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3503   //
3504   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3505   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3506     cut3DCurve[*it]=-1;
3507   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3508   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3509   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3510                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3511                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3512   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3513   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3514   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3515   if(cellIds2->empty())
3516     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3517   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3518   ret->setCoords(mDesc1->getCoords());
3519   ret->setConnectivity(conn,connI,true);
3520   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3521   return ret.retn();
3522 }
3523
3524 /*!
3525  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3526 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
3527 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3528 the result mesh.
3529  *  \param [in] origin - 3 components of a point defining location of the plane.
3530  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3531  *         must be greater than 1e-6.
3532  *  \param [in] eps - half-thickness of the plane.
3533  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3534  *         producing correspondent segments. The caller is to delete this array
3535  *         using decrRef() as it is no more needed.
3536  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3537  *         mesh in 3D space. This mesh does not share the node coordinates array with
3538  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3539  *         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() != 2 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 2D cell of \a this mesh.
3545  *  \throw If \a this includes quadratic cells.
3546  */
3547 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3548 {
3549   checkFullyDefined();
3550   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3551     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3552   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3553   if(candidates->empty())
3554     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3555   std::vector<int> nodes;
3556   DataArrayInt *cellIds1D(0);
3557   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3558   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3559   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3560   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3561   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3562   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3563   //
3564   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3565   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3566     cut3DCurve[*it]=-1;
3567   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3568   int ncellsSub=subMesh->getNumberOfCells();
3569   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3570   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3571                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3572                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3573   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3574   conn->alloc(0,1);
3575   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3576   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3577   for(int i=0;i<ncellsSub;i++)
3578     {
3579       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3580         {
3581           if(cut3DSurf[i].first!=-2)
3582             {
3583               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3584               connI->pushBackSilent(conn->getNumberOfTuples());
3585               cellIds2->pushBackSilent(i);
3586             }
3587           else
3588             {
3589               int cellId3DSurf=cut3DSurf[i].second;
3590               int offset=nodalI[cellId3DSurf]+1;
3591               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3592               for(int j=0;j<nbOfEdges;j++)
3593                 {
3594                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3595                   connI->pushBackSilent(conn->getNumberOfTuples());
3596                   cellIds2->pushBackSilent(cellId3DSurf);
3597                 }
3598             }
3599         }
3600     }
3601   if(cellIds2->empty())
3602     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3603   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3604   ret->setCoords(mDesc1->getCoords());
3605   ret->setConnectivity(conn,connI,true);
3606   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3607   return ret.retn();
3608 }
3609
3610 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3611 {
3612   checkFullyDefined();
3613   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3614     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3615   if(getNumberOfCells()!=1)
3616     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3617   //
3618   std::vector<int> nodes;
3619   findNodesOnPlane(origin,vec,eps,nodes);
3620   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());
3621   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3622   revDesc2=0; revDescIndx2=0;
3623   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3624   revDesc1=0; revDescIndx1=0;
3625   DataArrayInt *cellIds1D(0);
3626   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3627   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3628   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3629   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3630     cut3DCurve[*it]=-1;
3631   bool sameNbNodes;
3632   {
3633     int oldNbNodes(mDesc1->getNumberOfNodes());
3634     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3635     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3636   }
3637   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3638   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3639                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3640                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3641   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
3642   connI->pushBackSilent(0); conn->alloc(0,1);
3643   {
3644     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
3645     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3646     if(cellIds2->empty())
3647       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3648   }
3649   std::vector<std::vector<int> > res;
3650   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3651   std::size_t sz(res.size());
3652   if(res.size()==mDesc1->getNumberOfCells() && sameNbNodes)
3653     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3654   for(std::size_t i=0;i<sz;i++)
3655     {
3656       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
3657       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3658       connI->pushBackSilent(conn->getNumberOfTuples());
3659     }
3660   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3661   ret->setCoords(mDesc1->getCoords());
3662   ret->setConnectivity(conn,connI,true);
3663   int nbCellsRet(ret->getNumberOfCells());
3664   //
3665   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3666   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3667   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3668   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3669   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3670   MCAuto<DataArrayDouble> occm;
3671   {
3672     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3673     occm=DataArrayDouble::Substract(ccm,pt);
3674   }
3675   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3676   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);
3677   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3678   //
3679   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3680   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3681   ret2->setCoords(mDesc1->getCoords());
3682   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
3683   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3684   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
3685   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
3686   if(dott->getIJ(0,0)>0)
3687     {
3688       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3689       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3690     }
3691   else
3692     {
3693       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3694       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3695     }
3696   for(int i=1;i<nbCellsRet;i++)
3697     {
3698       if(dott2->getIJ(i,0)<0)
3699         {
3700           if(ciPtr[i+1]-ciPtr[i]>=4)
3701             {
3702               cell0.push_back(-1);
3703               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3704             }
3705         }
3706       else
3707         {
3708           if(ciPtr[i+1]-ciPtr[i]>=4)
3709             {
3710               cell1.push_back(-1);
3711               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3712             }
3713         }
3714     }
3715   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3716   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3717   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3718   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3719   ret2->setConnectivity(conn2,conn2I,true);
3720   ret2->checkConsistencyLight();
3721   ret2->orientCorrectlyPolyhedrons();
3722   return ret2;
3723 }
3724
3725 /*!
3726  * Finds cells whose bounding boxes intersect a given plane.
3727  *  \param [in] origin - 3 components of a point defining location of the plane.
3728  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3729  *         must be greater than 1e-6.
3730  *  \param [in] eps - half-thickness of the plane.
3731  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3732  *         cells. The caller is to delete this array using decrRef() as it is no more
3733  *         needed.
3734  *  \throw If the coordinates array is not set.
3735  *  \throw If the nodal connectivity of cells is not defined.
3736  *  \throw If \a this->getSpaceDimension() != 3.
3737  *  \throw If magnitude of \a vec is less than 1e-6.
3738  *  \sa buildSlice3D()
3739  */
3740 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3741 {
3742   checkFullyDefined();
3743   if(getSpaceDimension()!=3)
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3745   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3746   if(normm<1e-6)
3747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3748   double vec2[3];
3749   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3750   double angle=acos(vec[2]/normm);
3751   MCAuto<DataArrayInt> cellIds;
3752   double bbox[6];
3753   if(angle>eps)
3754     {
3755       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3756       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3757       if(normm2/normm>1e-6)
3758         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3759       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3760       mw->setCoords(coo);
3761       mw->getBoundingBox(bbox);
3762       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3763       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3764     }
3765   else
3766     {
3767       getBoundingBox(bbox);
3768       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3769       cellIds=getCellsInBoundingBox(bbox,eps);
3770     }
3771   return cellIds.retn();
3772 }
3773
3774 /*!
3775  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3776  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3777  * No consideration of coordinate is done by this method.
3778  * 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)
3779  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3780  */
3781 bool MEDCouplingUMesh::isContiguous1D() const
3782 {
3783   if(getMeshDimension()!=1)
3784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3785   int nbCells=getNumberOfCells();
3786   if(nbCells<1)
3787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3788   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3789   int ref=conn[connI[0]+2];
3790   for(int i=1;i<nbCells;i++)
3791     {
3792       if(conn[connI[i]+1]!=ref)
3793         return false;
3794       ref=conn[connI[i]+2];
3795     }
3796   return true;
3797 }
3798
3799 /*!
3800  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3801  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3802  * \param pt reference point of the line
3803  * \param v normalized director vector of the line
3804  * \param eps max precision before throwing an exception
3805  * \param res output of size this->getNumberOfCells
3806  */
3807 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3808 {
3809   if(getMeshDimension()!=1)
3810     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3811   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3812     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3813   if(getSpaceDimension()!=3)
3814     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3815   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3816   const double *fPtr=f->getArray()->getConstPointer();
3817   double tmp[3];
3818   for(int i=0;i<getNumberOfCells();i++)
3819     {
3820       const double *tmp1=fPtr+3*i;
3821       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3822       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3823       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3824       double n1=INTERP_KERNEL::norm<3>(tmp);
3825       n1/=INTERP_KERNEL::norm<3>(tmp1);
3826       if(n1>eps)
3827         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3828     }
3829   const double *coo=getCoords()->getConstPointer();
3830   for(int i=0;i<getNumberOfNodes();i++)
3831     {
3832       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3833       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3834       res[i]=std::accumulate(tmp,tmp+3,0.);
3835     }
3836 }
3837
3838 /*!
3839  * 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. 
3840  * \a this is expected to be a mesh so that its space dimension is equal to its
3841  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3842  * 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).
3843  *
3844  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3845  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3846  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3847  *
3848  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3849  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3850  *
3851  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3852  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3853  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3854  * \return the positive value of the distance.
3855  * \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
3856  * dimension - 1.
3857  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3858  */
3859 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3860 {
3861   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3862   if(meshDim!=spaceDim-1)
3863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3864   if(meshDim!=2 && meshDim!=1)
3865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3866   checkFullyDefined();
3867   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3868     { 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()); }
3869   DataArrayInt *ret1=0;
3870   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3871   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3872   MCAuto<DataArrayInt> ret1Safe(ret1);
3873   cellId=*ret1Safe->begin();
3874   return *ret0->begin();
3875 }
3876
3877 /*!
3878  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3879  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3880  * 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
3881  * 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).
3882  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3883  * 
3884  * \a this is expected to be a mesh so that its space dimension is equal to its
3885  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3886  * 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).
3887  *
3888  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3889  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3890  *
3891  * \param [in] pts the list of points in which each tuple represents a point
3892  * \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.
3893  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3894  * \throw if number of components of \a pts is not equal to the space dimension.
3895  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3896  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3897  */
3898 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3899 {
3900   if(!pts)
3901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3902   pts->checkAllocated();
3903   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3904   if(meshDim!=spaceDim-1)
3905     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3906   if(meshDim!=2 && meshDim!=1)
3907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3908   if(pts->getNumberOfComponents()!=spaceDim)
3909     {
3910       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3911       throw INTERP_KERNEL::Exception(oss.str());
3912     }
3913   checkFullyDefined();
3914   int nbCells=getNumberOfCells();
3915   if(nbCells==0)
3916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3917   int nbOfPts=pts->getNumberOfTuples();
3918   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3919   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3920   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3921   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3922   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3923   const double *bbox(bboxArr->begin());
3924   switch(spaceDim)
3925   {
3926     case 3:
3927       {
3928         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3929         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3930           {
3931             double x=std::numeric_limits<double>::max();
3932             std::vector<int> elems;
3933             myTree.getMinDistanceOfMax(ptsPtr,x);
3934             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3935             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3936           }
3937         break;
3938       }
3939     case 2:
3940       {
3941         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3942         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3943           {
3944             double x=std::numeric_limits<double>::max();
3945             std::vector<int> elems;
3946             myTree.getMinDistanceOfMax(ptsPtr,x);
3947             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3948             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3949           }
3950         break;
3951       }
3952     default:
3953       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3954   }
3955   cellIds=ret1.retn();
3956   return ret0.retn();
3957 }
3958
3959 /// @cond INTERNAL
3960
3961 /// @endcond
3962
3963 /*!
3964  * Finds cells in contact with a ball (i.e. a point with precision). 
3965  * 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.
3966  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
3967  *
3968  * \warning This method is suitable if the caller intends to evaluate only one
3969  *          point, for more points getCellsContainingPoints() is recommended as it is
3970  *          faster. 
3971  *  \param [in] pos - array of coordinates of the ball central point.
3972  *  \param [in] eps - ball radius.
3973  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
3974  *         if there are no such cells.
3975  *  \throw If the coordinates array is not set.
3976  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3977  */
3978 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3979 {
3980   std::vector<int> elts;
3981   getCellsContainingPoint(pos,eps,elts);
3982   if(elts.empty())
3983     return -1;
3984   return elts.front();
3985 }
3986
3987 /*!
3988  * Finds cells in contact with a ball (i.e. a point with precision).
3989  * 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.
3990  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
3991  * \warning This method is suitable if the caller intends to evaluate only one
3992  *          point, for more points getCellsContainingPoints() is recommended as it is
3993  *          faster. 
3994  *  \param [in] pos - array of coordinates of the ball central point.
3995  *  \param [in] eps - ball radius.
3996  *  \param [out] elts - vector returning ids of the found cells. It is cleared
3997  *         before inserting ids.
3998  *  \throw If the coordinates array is not set.
3999  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4000  *
4001  *  \if ENABLE_EXAMPLES
4002  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4003  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4004  *  \endif
4005  */
4006 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4007 {
4008   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4009   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4010   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4011 }
4012
4013 /*!
4014  * Finds cells in contact with several balls (i.e. points with precision).
4015  * This method is an extension of getCellContainingPoint() and
4016  * getCellsContainingPoint() for the case of multiple points.
4017  * 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.
4018  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4019  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4020  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4021  *         this->getSpaceDimension() * \a nbOfPoints 
4022  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4023  *  \param [in] eps - radius of balls (i.e. the precision).
4024  *  \param [out] elts - vector returning ids of found cells.
4025  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4026  *         dividing cell ids in \a elts into groups each referring to one
4027  *         point. Its every element (except the last one) is an index pointing to the
4028  *         first id of a group of cells. For example cells in contact with the *i*-th
4029  *         point are described by following range of indices:
4030  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4031  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4032  *         Number of cells in contact with the *i*-th point is
4033  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4034  *  \throw If the coordinates array is not set.
4035  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4036  *
4037  *  \if ENABLE_EXAMPLES
4038  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4039  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4040  *  \endif
4041  */
4042 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4043                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4044 {
4045   int spaceDim=getSpaceDimension();
4046   int mDim=getMeshDimension();
4047   if(spaceDim==3)
4048     {
4049       if(mDim==3)
4050         {
4051           const double *coords=_coords->getConstPointer();
4052           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4053         }
4054       /*else if(mDim==2)
4055         {
4056
4057         }*/
4058       else
4059         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4060     }
4061   else if(spaceDim==2)
4062     {
4063       if(mDim==2)
4064         {
4065           const double *coords=_coords->getConstPointer();
4066           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4067         }
4068       else
4069         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4070     }
4071   else if(spaceDim==1)
4072     {
4073       if(mDim==1)
4074         {
4075           const double *coords=_coords->getConstPointer();
4076           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4077         }
4078       else
4079         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4080     }
4081   else
4082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4083 }
4084
4085 /*!
4086  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4087  * least two its edges intersect each other anywhere except their extremities. An
4088  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4089  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4090  *         cleared before filling in.
4091  *  \param [in] eps - precision.
4092  *  \throw If \a this->getMeshDimension() != 2.
4093  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4094  */
4095 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4096 {
4097   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4098   if(getMeshDimension()!=2)
4099     throw INTERP_KERNEL::Exception(msg);
4100   int spaceDim=getSpaceDimension();
4101   if(spaceDim!=2 && spaceDim!=3)
4102     throw INTERP_KERNEL::Exception(msg);
4103   const int *conn=_nodal_connec->getConstPointer();
4104   const int *connI=_nodal_connec_index->getConstPointer();
4105   int nbOfCells=getNumberOfCells();
4106   std::vector<double> cell2DinS2;
4107   for(int i=0;i<nbOfCells;i++)
4108     {
4109       int offset=connI[i];
4110       int nbOfNodesForCell=connI[i+1]-offset-1;
4111       if(nbOfNodesForCell<=3)
4112         continue;
4113       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4114       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4115       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4116         cells.push_back(i);
4117       cell2DinS2.clear();
4118     }
4119 }
4120
4121 /*!
4122  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4123  *
4124  * 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.
4125  * 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.
4126  * 
4127  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4128  * This convex envelop is computed using Jarvis march algorithm.
4129  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4130  * 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)
4131  * 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.
4132  *
4133  * \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.
4134  * \sa MEDCouplingUMesh::colinearize2D
4135  */
4136 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4137 {
4138   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4139     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4140   checkFullyDefined();
4141   const double *coords=getCoords()->getConstPointer();
4142   int nbOfCells=getNumberOfCells();
4143   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4144   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4145   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4146   int *workIndexOut=nodalConnecIndexOut->getPointer();
4147   *workIndexOut=0;
4148   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4149   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4150   std::set<INTERP_KERNEL::NormalizedCellType> types;
4151   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4152   isChanged->alloc(0,1);
4153   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4154     {
4155       int pos=nodalConnecOut->getNumberOfTuples();
4156       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4157         isChanged->pushBackSilent(i);
4158       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4159       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4160     }
4161   if(isChanged->empty())
4162     return 0;
4163   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4164   _types=types;
4165   return isChanged.retn();
4166 }
4167
4168 /*!
4169  * This method is \b NOT const because it can modify \a this.
4170  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4171  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4172  * \param policy specifies the type of extrusion chosen:
4173  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4174  *   will be repeated to build each level
4175  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4176  *   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
4177  *   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
4178  *   arc.
4179  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4180  */
4181 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4182 {
4183   checkFullyDefined();
4184   mesh1D->checkFullyDefined();
4185   if(!mesh1D->isContiguous1D())
4186     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4187   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4188     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4189   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4190     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4191   if(mesh1D->getMeshDimension()!=1)
4192     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4193   bool isQuad=false;
4194   if(isPresenceOfQuadratic())
4195     {
4196       if(mesh1D->isFullyQuadratic())
4197         isQuad=true;
4198       else
4199         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4200     }
4201   int oldNbOfNodes(getNumberOfNodes());
4202   MCAuto<DataArrayDouble> newCoords;
4203   switch(policy)
4204   {
4205     case 0:
4206       {
4207         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4208         break;
4209       }
4210     case 1:
4211       {
4212         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4213         break;
4214       }
4215     default:
4216       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4217   }
4218   setCoords(newCoords);
4219   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4220   updateTime();
4221   return ret.retn();
4222 }
4223
4224
4225 /*!
4226  * Checks if \a this mesh is constituted by only quadratic cells.
4227  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4228  *  \throw If the coordinates array is not set.
4229  *  \throw If the nodal connectivity of cells is not defined.
4230  */
4231 bool MEDCouplingUMesh::isFullyQuadratic() const
4232 {
4233   checkFullyDefined();
4234   bool ret=true;
4235   int nbOfCells=getNumberOfCells();
4236   for(int i=0;i<nbOfCells && ret;i++)
4237     {
4238       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4239       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4240       ret=cm.isQuadratic();
4241     }
4242   return ret;
4243 }
4244
4245 /*!
4246  * Checks if \a this mesh includes any quadratic cell.
4247  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4248  *  \throw If the coordinates array is not set.
4249  *  \throw If the nodal connectivity of cells is not defined.
4250  */
4251 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4252 {
4253   checkFullyDefined();
4254   bool ret=false;
4255   int nbOfCells=getNumberOfCells();
4256   for(int i=0;i<nbOfCells && !ret;i++)
4257     {
4258       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4259       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4260       ret=cm.isQuadratic();
4261     }
4262   return ret;
4263 }
4264
4265 /*!
4266  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4267  * this mesh, it remains unchanged.
4268  *  \throw If the coordinates array is not set.
4269  *  \throw If the nodal connectivity of cells is not defined.
4270  */
4271 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4272 {
4273   checkFullyDefined();
4274   int nbOfCells(getNumberOfCells());
4275   int delta=0;
4276   const int *iciptr=_nodal_connec_index->begin();
4277   for(int i=0;i<nbOfCells;i++)
4278     {
4279       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4280       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4281       if(cm.isQuadratic())
4282         {
4283           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4284           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4285           if(!cml.isDynamic())
4286             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4287           else
4288             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4289         }
4290     }
4291   if(delta==0)
4292     return ;
4293   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4294   const int *icptr(_nodal_connec->begin());
4295   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4296   newConnI->alloc(nbOfCells+1,1);
4297   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4298   *ociptr=0;
4299   _types.clear();
4300   for(int i=0;i<nbOfCells;i++,ociptr++)
4301     {
4302       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4303       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4304       if(!cm.isQuadratic())
4305         {
4306           _types.insert(type);
4307           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4308           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4309         }
4310       else
4311         {
4312           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4313           _types.insert(typel);
4314           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4315           int newNbOfNodes=cml.getNumberOfNodes();
4316           if(cml.isDynamic())
4317             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4318           *ocptr++=(int)typel;
4319           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4320           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4321         }
4322     }
4323   setConnectivity(newConn,newConnI,false);
4324 }
4325
4326 /*!
4327  * This method converts all linear cell in \a this to quadratic one.
4328  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4329  * 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)
4330  * 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.
4331  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4332  * end of the existing coordinates.
4333  * 
4334  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4335  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4336  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4337  * 
4338  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4339  *
4340  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4341  */
4342 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4343 {
4344   DataArrayInt *conn=0,*connI=0;
4345   DataArrayDouble *coords=0;
4346   std::set<INTERP_KERNEL::NormalizedCellType> types;
4347   checkFullyDefined();
4348   MCAuto<DataArrayInt> ret,connSafe,connISafe;
4349   MCAuto<DataArrayDouble> coordsSafe;
4350   int meshDim=getMeshDimension();
4351   switch(conversionType)
4352   {
4353     case 0:
4354       switch(meshDim)
4355       {
4356         case 1:
4357           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4358           connSafe=conn; connISafe=connI; coordsSafe=coords;
4359           break;
4360         case 2:
4361           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4362           connSafe=conn; connISafe=connI; coordsSafe=coords;
4363           break;
4364         case 3:
4365           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4366           connSafe=conn; connISafe=connI; coordsSafe=coords;
4367           break;
4368         default:
4369           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4370       }
4371       break;
4372         case 1:
4373           {
4374             switch(meshDim)
4375             {
4376               case 1:
4377                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4378                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4379                 break;
4380               case 2:
4381                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4382                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4383                 break;
4384               case 3:
4385                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4386                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4387                 break;
4388               default:
4389                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4390             }
4391             break;
4392           }
4393         default:
4394           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4395   }
4396   setConnectivity(connSafe,connISafe,false);
4397   _types=types;
4398   setCoords(coordsSafe);
4399   return ret.retn();
4400 }
4401
4402 /*!
4403  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4404  * so that the number of cells remains the same. Quadratic faces are converted to
4405  * polygons. This method works only for 2D meshes in
4406  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4407  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4408  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4409  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4410  *         a polylinized edge constituting the input polygon.
4411  *  \throw If the coordinates array is not set.
4412  *  \throw If the nodal connectivity of cells is not defined.
4413  *  \throw If \a this->getMeshDimension() != 2.
4414  *  \throw If \a this->getSpaceDimension() != 2.
4415  */
4416 void MEDCouplingUMesh::tessellate2D(double eps)
4417 {
4418   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4419   if(spaceDim!=2)
4420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4421   switch(meshDim)
4422     {
4423     case 1:
4424       return tessellate2DCurveInternal(eps);
4425     case 2:
4426       return tessellate2DInternal(eps);
4427     default:
4428       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4429     }
4430 }
4431 /*!
4432  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
4433  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4434  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
4435  *         a sub-divided edge.
4436  *  \throw If the coordinates array is not set.
4437  *  \throw If the nodal connectivity of cells is not defined.
4438  *  \throw If \a this->getMeshDimension() != 1.
4439  *  \throw If \a this->getSpaceDimension() != 2.
4440  */
4441
4442 #if 0
4443 /*!
4444  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4445  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4446  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4447  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4448  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4449  * This method can be seen as the opposite method of colinearize2D.
4450  * 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
4451  * to avoid to modify the numbering of existing nodes.
4452  *
4453  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4454  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4455  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4456  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4457  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4458  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4459  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4460  *
4461  * \sa buildDescendingConnectivity2
4462  */
4463 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
4464                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
4465 {
4466   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4468   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4469   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4470     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4471   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4473   //DataArrayInt *out0(0),*outi0(0);
4474   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4475   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
4476   //out0s=out0s->buildUnique(); out0s->sort(true);
4477 }
4478 #endif
4479
4480
4481 /*!
4482  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4483  * In addition, returns an array mapping new cells to old ones. <br>
4484  * This method typically increases the number of cells in \a this mesh
4485  * but the number of nodes remains \b unchanged.
4486  * That's why the 3D splitting policies
4487  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4488  *  \param [in] policy - specifies a pattern used for splitting.
4489  * The semantic of \a policy is:
4490  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4491  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4492  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4493  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4494  *
4495  *
4496  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
4497  *          an id of old cell producing it. The caller is to delete this array using
4498  *         decrRef() as it is no more needed.
4499  *
4500  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4501  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4502  *          and \a this->getMeshDimension() != 3. 
4503  *  \throw If \a policy is not one of the four discussed above.
4504  *  \throw If the nodal connectivity of cells is not defined.
4505  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4506  */
4507 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
4508 {
4509   switch(policy)
4510   {
4511     case 0:
4512       return simplexizePol0();
4513     case 1:
4514       return simplexizePol1();
4515     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4516         return simplexizePlanarFace5();
4517     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4518         return simplexizePlanarFace6();
4519     default:
4520       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)");
4521   }
4522 }
4523
4524 /*!
4525  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4526  * - 1D: INTERP_KERNEL::NORM_SEG2
4527  * - 2D: INTERP_KERNEL::NORM_TRI3
4528  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4529  *
4530  * This method is useful for users that need to use P1 field services as
4531  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4532  * All these methods need mesh support containing only simplex cells.
4533  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4534  *  \throw If the coordinates array is not set.
4535  *  \throw If the nodal connectivity of cells is not defined.
4536  *  \throw If \a this->getMeshDimension() < 1.
4537  */
4538 bool MEDCouplingUMesh::areOnlySimplexCells() const
4539 {
4540   checkFullyDefined();
4541   int mdim=getMeshDimension();
4542   if(mdim<1 || mdim>3)
4543     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4544   int nbCells=getNumberOfCells();
4545   const int *conn=_nodal_connec->begin();
4546   const int *connI=_nodal_connec_index->begin();
4547   for(int i=0;i<nbCells;i++)
4548     {
4549       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4550       if(!cm.isSimplex())
4551         return false;
4552     }
4553   return true;
4554 }
4555
4556
4557
4558 /*!
4559  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4560  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4561  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
4562  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
4563  * so it can be useful to call mergeNodes() before calling this method.
4564  *  \throw If \a this->getMeshDimension() <= 1.
4565  *  \throw If the coordinates array is not set.
4566  *  \throw If the nodal connectivity of cells is not defined.
4567  */
4568 void MEDCouplingUMesh::convertDegeneratedCells()
4569 {
4570   checkFullyDefined();
4571   if(getMeshDimension()<=1)
4572     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4573   int nbOfCells=getNumberOfCells();
4574   if(nbOfCells<1)
4575     return ;
4576   int initMeshLgth=getNodalConnectivityArrayLen();
4577   int *conn=_nodal_connec->getPointer();
4578   int *index=_nodal_connec_index->getPointer();
4579   int posOfCurCell=0;
4580   int newPos=0;
4581   int lgthOfCurCell;
4582   for(int i=0;i<nbOfCells;i++)
4583     {
4584       lgthOfCurCell=index[i+1]-posOfCurCell;
4585       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4586       int newLgth;
4587       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4588                                                                                                      conn+newPos+1,newLgth);
4589       conn[newPos]=newType;
4590       newPos+=newLgth+1;
4591       posOfCurCell=index[i+1];
4592       index[i+1]=newPos;
4593     }
4594   if(newPos!=initMeshLgth)
4595     _nodal_connec->reAlloc(newPos);
4596   computeTypes();
4597 }
4598
4599 /*!
4600  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4601  * A cell is considered to be oriented correctly if an angle between its
4602  * normal vector and a given vector is less than \c PI / \c 2.
4603  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4604  *         cells. 
4605  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4606  *         checked.
4607  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4608  *         is not cleared before filling in.
4609  *  \throw If \a this->getMeshDimension() != 2.
4610  *  \throw If \a this->getSpaceDimension() != 3.
4611  *
4612  *  \if ENABLE_EXAMPLES
4613  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4614  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4615  *  \endif
4616  */
4617 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
4618 {
4619   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4620     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4621   int nbOfCells=getNumberOfCells();
4622   const int *conn=_nodal_connec->begin();
4623   const int *connI=_nodal_connec_index->begin();
4624   const double *coordsPtr=_coords->begin();
4625   for(int i=0;i<nbOfCells;i++)
4626     {
4627       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4628       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4629         {
4630           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4631           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4632             cells.push_back(i);
4633         }
4634     }
4635 }
4636
4637 /*!
4638  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4639  * considered to be oriented correctly if an angle between its normal vector and a
4640  * given vector is less than \c PI / \c 2. 
4641  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4642  *         cells. 
4643  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4644  *         checked.
4645  *  \throw If \a this->getMeshDimension() != 2.
4646  *  \throw If \a this->getSpaceDimension() != 3.
4647  *
4648  *  \if ENABLE_EXAMPLES
4649  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4650  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4651  *  \endif
4652  *
4653  *  \sa changeOrientationOfCells
4654  */
4655 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4656 {
4657   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4658     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4659   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4660   const int *connI(_nodal_connec_index->begin());
4661   const double *coordsPtr(_coords->begin());
4662   bool isModified(false);
4663   for(int i=0;i<nbOfCells;i++)
4664     {
4665       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4666       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4667         {
4668           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4669           bool isQuadratic(cm.isQuadratic());
4670           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4671             {
4672               isModified=true;
4673               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4674             }
4675         }
4676     }
4677   if(isModified)
4678     _nodal_connec->declareAsNew();
4679   updateTime();
4680 }
4681
4682 /*!
4683  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4684  *
4685  * \sa orientCorrectly2DCells
4686  */
4687 void MEDCouplingUMesh::changeOrientationOfCells()
4688 {
4689   int mdim(getMeshDimension());
4690   if(mdim!=2 && mdim!=1)
4691     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4692   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
4693   const int *connI(_nodal_connec_index->begin());
4694   if(mdim==2)
4695     {//2D
4696       for(int i=0;i<nbOfCells;i++)
4697         {
4698           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4699           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4700           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4701         }
4702     }
4703   else
4704     {//1D
4705       for(int i=0;i<nbOfCells;i++)
4706         {
4707           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4708           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4709           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4710         }
4711     }
4712 }
4713
4714 /*!
4715  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4716  * oriented facets. The normal vector of the facet should point out of the cell.
4717  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4718  *         is not cleared before filling in.
4719  *  \throw If \a this->getMeshDimension() != 3.
4720  *  \throw If \a this->getSpaceDimension() != 3.
4721  *  \throw If the coordinates array is not set.
4722  *  \throw If the nodal connectivity of cells is not defined.
4723  *
4724  *  \if ENABLE_EXAMPLES
4725  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4726  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4727  *  \endif
4728  */
4729 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
4730 {
4731   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4732     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4733   int nbOfCells=getNumberOfCells();
4734   const int *conn=_nodal_connec->begin();
4735   const int *connI=_nodal_connec_index->begin();
4736   const double *coordsPtr=_coords->begin();
4737   for(int i=0;i<nbOfCells;i++)
4738     {
4739       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4740       if(type==INTERP_KERNEL::NORM_POLYHED)
4741         {
4742           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4743             cells.push_back(i);
4744         }
4745     }
4746 }
4747
4748 /*!
4749  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4750  * out of the cell. 
4751  *  \throw If \a this->getMeshDimension() != 3.
4752  *  \throw If \a this->getSpaceDimension() != 3.
4753  *  \throw If the coordinates array is not set.
4754  *  \throw If the nodal connectivity of cells is not defined.
4755  *  \throw If the reparation fails.
4756  *
4757  *  \if ENABLE_EXAMPLES
4758  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4759  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4760  *  \endif
4761  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4762  */
4763 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4764 {
4765   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4766     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4767   int nbOfCells=getNumberOfCells();
4768   int *conn=_nodal_connec->getPointer();
4769   const int *connI=_nodal_connec_index->begin();
4770   const double *coordsPtr=_coords->begin();
4771   for(int i=0;i<nbOfCells;i++)
4772     {
4773       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4774       if(type==INTERP_KERNEL::NORM_POLYHED)
4775         {
4776           try
4777           {
4778               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4779                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4780           }
4781           catch(INTERP_KERNEL::Exception& e)
4782           {
4783               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4784               throw INTERP_KERNEL::Exception(oss.str());
4785           }
4786         }
4787     }
4788   updateTime();
4789 }
4790
4791 /*!
4792  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
4793  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
4794  * according to which the first facet of the cell should be oriented to have the normal vector
4795  * pointing out of cell.
4796  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
4797  *         cells. The caller is to delete this array using decrRef() as it is no more
4798  *         needed. 
4799  *  \throw If \a this->getMeshDimension() != 3.
4800  *  \throw If \a this->getSpaceDimension() != 3.
4801  *  \throw If the coordinates array is not set.
4802  *  \throw If the nodal connectivity of cells is not defined.
4803  *
4804  *  \if ENABLE_EXAMPLES
4805  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
4806  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
4807  *  \endif
4808  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4809  */
4810 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
4811 {
4812   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
4813   if(getMeshDimension()!=3)
4814     throw INTERP_KERNEL::Exception(msg);
4815   int spaceDim=getSpaceDimension();
4816   if(spaceDim!=3)
4817     throw INTERP_KERNEL::Exception(msg);
4818   //
4819   int nbOfCells=getNumberOfCells();
4820   int *conn=_nodal_connec->getPointer();
4821   const int *connI=_nodal_connec_index->begin();
4822   const double *coo=getCoords()->begin();
4823   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
4824   for(int i=0;i<nbOfCells;i++)
4825     {
4826       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4827       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
4828         {
4829           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
4830             {
4831               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4832               cells->pushBackSilent(i);
4833             }
4834         }
4835     }
4836   return cells.retn();
4837 }
4838
4839 /*!
4840  * This method is a faster method to correct orientation of all 3D cells in \a this.
4841  * 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.
4842  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
4843  * 
4844  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
4845  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
4846  */
4847 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
4848 {
4849   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4850     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
4851   int nbOfCells=getNumberOfCells();
4852   int *conn=_nodal_connec->getPointer();
4853   const int *connI=_nodal_connec_index->begin();
4854   const double *coordsPtr=_coords->begin();
4855   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4856   for(int i=0;i<nbOfCells;i++)
4857     {
4858       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4859       switch(type)
4860       {
4861         case INTERP_KERNEL::NORM_TETRA4:
4862           {
4863             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4864               {
4865                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
4866                 ret->pushBackSilent(i);
4867               }
4868             break;
4869           }
4870         case INTERP_KERNEL::NORM_PYRA5:
4871           {
4872             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4873               {
4874                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
4875                 ret->pushBackSilent(i);
4876               }
4877             break;
4878           }
4879         case INTERP_KERNEL::NORM_PENTA6:
4880         case INTERP_KERNEL::NORM_HEXA8:
4881         case INTERP_KERNEL::NORM_HEXGP12:
4882           {
4883             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4884               {
4885                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
4886                 ret->pushBackSilent(i);
4887               }
4888             break;
4889           }
4890         case INTERP_KERNEL::NORM_POLYHED:
4891           {
4892             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4893               {
4894                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4895                 ret->pushBackSilent(i);
4896               }
4897             break;
4898           }
4899         default:
4900           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 !");
4901       }
4902     }
4903   updateTime();
4904   return ret.retn();
4905 }
4906
4907 /*!
4908  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
4909  * If it is not the case an exception will be thrown.
4910  * This method is fast because the first cell of \a this is used to compute the plane.
4911  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
4912  * \param pos output of size at least 3 used to store a point owned of searched plane.
4913  */
4914 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
4915 {
4916   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4917     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
4918   const int *conn=_nodal_connec->begin();
4919   const int *connI=_nodal_connec_index->begin();
4920   const double *coordsPtr=_coords->begin();
4921   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
4922   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
4923 }
4924
4925 /*!
4926  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
4927  * cells. Currently cells of the following types are treated:
4928  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
4929  * For a cell of other type an exception is thrown.
4930  * Space dimension of a 2D mesh can be either 2 or 3.
4931  * The Edge Ratio of a cell \f$t\f$ is: 
4932  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
4933  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
4934  *  the smallest edge lengths of \f$t\f$.
4935  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
4936  *          cells and one time, lying on \a this mesh. The caller is to delete this
4937  *          field using decrRef() as it is no more needed. 
4938  *  \throw If the coordinates array is not set.
4939  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
4940  *  \throw If the connectivity data array has more than one component.
4941  *  \throw If the connectivity data array has a named component.
4942  *  \throw If the connectivity index data array has more than one component.
4943  *  \throw If the connectivity index data array has a named component.
4944  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
4945  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
4946  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
4947  */
4948 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
4949 {
4950   checkConsistencyLight();
4951   int spaceDim=getSpaceDimension();
4952   int meshDim=getMeshDimension();
4953   if(spaceDim!=2 && spaceDim!=3)
4954     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
4955   if(meshDim!=2 && meshDim!=3)
4956     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
4957   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
4958   ret->setMesh(this);
4959   int nbOfCells=getNumberOfCells();
4960   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
4961   arr->alloc(nbOfCells,1);
4962   double *pt=arr->getPointer();
4963   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
4964   const int *conn=_nodal_connec->begin();
4965   const int *connI=_nodal_connec_index->begin();
4966   const double *coo=_coords->begin();
4967   double tmp[12];
4968   for(int i=0;i<nbOfCells;i++,pt++)
4969     {
4970       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
4971       switch(t)
4972       {
4973         case INTERP_KERNEL::NORM_TRI3:
4974           {
4975             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
4976             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
4977             break;
4978           }
4979         case INTERP_KERNEL::NORM_QUAD4:
4980           {
4981             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4982             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
4983             break;
4984           }
4985         case INTERP_KERNEL::NORM_TETRA4:
4986           {
4987             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
4988             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
4989             break;
4990           }
4991         default:
4992           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
4993       }
4994       conn+=connI[i+1]-connI[i];
4995     }
4996   ret->setName("EdgeRatio");
4997   ret->synchronizeTimeWithSupport();
4998   return ret.retn();
4999 }
5000
5001 /*!
5002  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5003  * cells. Currently cells of the following types are treated:
5004  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5005  * For a cell of other type an exception is thrown.
5006  * Space dimension of a 2D mesh can be either 2 or 3.
5007  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5008  *          cells and one time, lying on \a this mesh. The caller is to delete this
5009  *          field using decrRef() as it is no more needed. 
5010  *  \throw If the coordinates array is not set.
5011  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5012  *  \throw If the connectivity data array has more than one component.
5013  *  \throw If the connectivity data array has a named component.
5014  *  \throw If the connectivity index data array has more than one component.
5015  *  \throw If the connectivity index data array has a named component.
5016  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5017  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5018  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5019  */
5020 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5021 {
5022   checkConsistencyLight();
5023   int spaceDim=getSpaceDimension();
5024   int meshDim=getMeshDimension();
5025   if(spaceDim!=2 && spaceDim!=3)
5026     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5027   if(meshDim!=2 && meshDim!=3)
5028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5029   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5030   ret->setMesh(this);
5031   int nbOfCells=getNumberOfCells();
5032   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5033   arr->alloc(nbOfCells,1);
5034   double *pt=arr->getPointer();
5035   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5036   const int *conn=_nodal_connec->begin();
5037   const int *connI=_nodal_connec_index->begin();
5038   const double *coo=_coords->begin();
5039   double tmp[12];
5040   for(int i=0;i<nbOfCells;i++,pt++)
5041     {
5042       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5043       switch(t)
5044       {
5045         case INTERP_KERNEL::NORM_TRI3:
5046           {
5047             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5048             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5049             break;
5050           }
5051         case INTERP_KERNEL::NORM_QUAD4:
5052           {
5053             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5054             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5055             break;
5056           }
5057         case INTERP_KERNEL::NORM_TETRA4:
5058           {
5059             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5060             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5061             break;
5062           }
5063         default:
5064           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5065       }
5066       conn+=connI[i+1]-connI[i];
5067     }
5068   ret->setName("AspectRatio");
5069   ret->synchronizeTimeWithSupport();
5070   return ret.retn();
5071 }
5072
5073 /*!
5074  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5075  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5076  * in 3D space. Currently only cells of the following types are
5077  * treated: INTERP_KERNEL::NORM_QUAD4.
5078  * For a cell of other type an exception is thrown.
5079  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5080  * Defining
5081  * \f$t=\vec{da}\times\vec{ab}\f$,
5082  * \f$u=\vec{ab}\times\vec{bc}\f$
5083  * \f$v=\vec{bc}\times\vec{cd}\f$
5084  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5085  *  \f[
5086  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5087  *  \f]
5088  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5089  *          cells and one time, lying on \a this mesh. The caller is to delete this
5090  *          field using decrRef() as it is no more needed. 
5091  *  \throw If the coordinates array is not set.
5092  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5093  *  \throw If the connectivity data array has more than one component.
5094  *  \throw If the connectivity data array has a named component.
5095  *  \throw If the connectivity index data array has more than one component.
5096  *  \throw If the connectivity index data array has a named component.
5097  *  \throw If \a this->getMeshDimension() != 2.
5098  *  \throw If \a this->getSpaceDimension() != 3.
5099  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5100  */
5101 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5102 {
5103   checkConsistencyLight();
5104   int spaceDim=getSpaceDimension();
5105   int meshDim=getMeshDimension();
5106   if(spaceDim!=3)
5107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5108   if(meshDim!=2)
5109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5110   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5111   ret->setMesh(this);
5112   int nbOfCells=getNumberOfCells();
5113   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5114   arr->alloc(nbOfCells,1);
5115   double *pt=arr->getPointer();
5116   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5117   const int *conn=_nodal_connec->begin();
5118   const int *connI=_nodal_connec_index->begin();
5119   const double *coo=_coords->begin();
5120   double tmp[12];
5121   for(int i=0;i<nbOfCells;i++,pt++)
5122     {
5123       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5124       switch(t)
5125       {
5126         case INTERP_KERNEL::NORM_QUAD4:
5127           {
5128             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5129             *pt=INTERP_KERNEL::quadWarp(tmp);
5130             break;
5131           }
5132         default:
5133           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5134       }
5135       conn+=connI[i+1]-connI[i];
5136     }
5137   ret->setName("Warp");
5138   ret->synchronizeTimeWithSupport();
5139   return ret.retn();
5140 }
5141
5142
5143 /*!
5144  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5145  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5146  * treated: INTERP_KERNEL::NORM_QUAD4.
5147  * The skew is computed as follow for a quad with points (a,b,c,d): let
5148  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5149  * then the skew is computed as:
5150  *  \f[
5151  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5152  *  \f]
5153  *
5154  * For a cell of other type an exception is thrown.
5155  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5156  *          cells and one time, lying on \a this mesh. The caller is to delete this
5157  *          field using decrRef() as it is no more needed. 
5158  *  \throw If the coordinates array is not set.
5159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5160  *  \throw If the connectivity data array has more than one component.
5161  *  \throw If the connectivity data array has a named component.
5162  *  \throw If the connectivity index data array has more than one component.
5163  *  \throw If the connectivity index data array has a named component.
5164  *  \throw If \a this->getMeshDimension() != 2.
5165  *  \throw If \a this->getSpaceDimension() != 3.
5166  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5167  */
5168 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5169 {
5170   checkConsistencyLight();
5171   int spaceDim=getSpaceDimension();
5172   int meshDim=getMeshDimension();
5173   if(spaceDim!=3)
5174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5175   if(meshDim!=2)
5176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5177   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5178   ret->setMesh(this);
5179   int nbOfCells=getNumberOfCells();
5180   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5181   arr->alloc(nbOfCells,1);
5182   double *pt=arr->getPointer();
5183   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5184   const int *conn=_nodal_connec->begin();
5185   const int *connI=_nodal_connec_index->begin();
5186   const double *coo=_coords->begin();
5187   double tmp[12];
5188   for(int i=0;i<nbOfCells;i++,pt++)
5189     {
5190       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5191       switch(t)
5192       {
5193         case INTERP_KERNEL::NORM_QUAD4:
5194           {
5195             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5196             *pt=INTERP_KERNEL::quadSkew(tmp);
5197             break;
5198           }
5199         default:
5200           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5201       }
5202       conn+=connI[i+1]-connI[i];
5203     }
5204   ret->setName("Skew");
5205   ret->synchronizeTimeWithSupport();
5206   return ret.retn();
5207 }
5208
5209 /*!
5210  * 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.
5211  *
5212  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5213  *
5214  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5215  */
5216 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5217 {
5218   checkConsistencyLight();
5219   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5220   ret->setMesh(this);
5221   std::set<INTERP_KERNEL::NormalizedCellType> types;
5222   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5223   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
5224   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5225   arr->alloc(nbCells,1);
5226   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5227     {
5228       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5229       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
5230       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5231     }
5232   ret->setArray(arr);
5233   ret->setName("Diameter");
5234   return ret.retn();
5235 }
5236
5237 /*!
5238  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5239  * 
5240  * \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)
5241  *                         For all other cases this input parameter is ignored.
5242  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5243  * 
5244  * \throw If \a this is not fully set (coordinates and connectivity).
5245  * \throw If a cell in \a this has no valid nodeId.
5246  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5247  */
5248 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5249 {
5250   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5251   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.
5252     return getBoundingBoxForBBTreeFast();
5253   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5254     {
5255       bool presenceOfQuadratic(false);
5256       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5257         {
5258           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5259           if(cm.isQuadratic())
5260             presenceOfQuadratic=true;
5261         }
5262       if(!presenceOfQuadratic)
5263         return getBoundingBoxForBBTreeFast();
5264       if(mDim==2 && sDim==2)
5265         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5266       else
5267         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5268     }
5269   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) !");
5270 }
5271
5272 /*!
5273  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5274  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5275  * 
5276  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5277  * 
5278  * \throw If \a this is not fully set (coordinates and connectivity).
5279  * \throw If a cell in \a this has no valid nodeId.
5280  */
5281 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5282 {
5283   checkFullyDefined();
5284   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
5285   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5286   double *bbox(ret->getPointer());
5287   for(int i=0;i<nbOfCells*spaceDim;i++)
5288     {
5289       bbox[2*i]=std::numeric_limits<double>::max();
5290       bbox[2*i+1]=-std::numeric_limits<double>::max();
5291     }
5292   const double *coordsPtr(_coords->begin());
5293   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5294   for(int i=0;i<nbOfCells;i++)
5295     {
5296       int offset=connI[i]+1;
5297       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
5298       for(int j=0;j<nbOfNodesForCell;j++)
5299         {
5300           int nodeId=conn[offset+j];
5301           if(nodeId>=0 && nodeId<nbOfNodes)
5302             {
5303               for(int k=0;k<spaceDim;k++)
5304                 {
5305                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5306                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5307                 }
5308               kk++;
5309             }
5310         }
5311       if(kk==0)
5312         {
5313           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5314           throw INTERP_KERNEL::Exception(oss.str());
5315         }
5316     }
5317   return ret.retn();
5318 }
5319
5320 /*!
5321  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5322  * useful for 2D meshes having quadratic cells
5323  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5324  * the two extremities of the arc of circle).
5325  * 
5326  * \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)
5327  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5328  * \throw If \a this is not fully defined.
5329  * \throw If \a this is not a mesh with meshDimension equal to 2.
5330  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5331  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5332  */
5333 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5334 {
5335   checkFullyDefined();
5336   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5337   if(spaceDim!=2 || mDim!=2)
5338     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!");
5339   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5340   double *bbox(ret->getPointer());
5341   const double *coords(_coords->begin());
5342   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5343   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5344     {
5345       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5346       int sz(connI[1]-connI[0]-1);
5347       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
5348       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5349       INTERP_KERNEL::QuadraticPolygon *pol(0);
5350       for(int j=0;j<sz;j++)
5351         {
5352           int nodeId(conn[*connI+1+j]);
5353           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5354         }
5355       if(!cm.isQuadratic())
5356         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5357       else
5358         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5359       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5360       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
5361     }
5362   return ret.retn();
5363 }
5364
5365 /*!
5366  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5367  * useful for 2D meshes having quadratic cells
5368  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5369  * the two extremities of the arc of circle).
5370  * 
5371  * \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)
5372  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5373  * \throw If \a this is not fully defined.
5374  * \throw If \a this is not a mesh with meshDimension equal to 1.
5375  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5376  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5377  */
5378 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5379 {
5380   checkFullyDefined();
5381   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
5382   if(spaceDim!=2 || mDim!=1)
5383     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!");
5384   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5385   double *bbox(ret->getPointer());
5386   const double *coords(_coords->begin());
5387   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5388   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
5389     {
5390       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5391       int sz(connI[1]-connI[0]-1);
5392       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
5393       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5394       INTERP_KERNEL::Edge *edge(0);
5395       for(int j=0;j<sz;j++)
5396         {
5397           int nodeId(conn[*connI+1+j]);
5398           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5399         }
5400       if(!cm.isQuadratic())
5401         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5402       else
5403         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5404       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5405       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5406     }
5407   return ret.retn();
5408 }
5409
5410 /// @cond INTERNAL
5411
5412 namespace MEDCouplingImpl
5413 {
5414   class ConnReader
5415   {
5416   public:
5417     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5418     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5419   private:
5420     const int *_conn;
5421     int _val;
5422   };
5423
5424   class ConnReader2
5425   {
5426   public:
5427     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5428     bool operator() (const int& pos) { return _conn[pos]==_val; }
5429   private:
5430     const int *_conn;
5431     int _val;
5432   };
5433 }
5434
5435 /// @endcond
5436
5437 /*!
5438  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5439  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5440  * \a this is composed in cell types.
5441  * The returned array is of size 3*n where n is the number of different types present in \a this. 
5442  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
5443  * This parameter is kept only for compatibility with other methode listed above.
5444  */
5445 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
5446 {
5447   checkConnectivityFullyDefined();
5448   const int *conn=_nodal_connec->begin();
5449   const int *connI=_nodal_connec_index->begin();
5450   const int *work=connI;
5451   int nbOfCells=getNumberOfCells();
5452   std::size_t n=getAllGeoTypes().size();
5453   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5454   std::set<INTERP_KERNEL::NormalizedCellType> types;
5455   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5456     {
5457       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5458       if(types.find(typ)!=types.end())
5459         {
5460           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5461           oss << " is not contiguous !";
5462           throw INTERP_KERNEL::Exception(oss.str());
5463         }
5464       types.insert(typ);
5465       ret[3*i]=typ;
5466       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5467       ret[3*i+1]=(int)std::distance(work,work2);
5468       work=work2;
5469     }
5470   return ret;
5471 }
5472
5473 /*!
5474  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5475  * only for types cell, type node is not managed.
5476  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5477  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5478  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5479  * If 2 or more same geometric type is in \a code and exception is thrown too.
5480  *
5481  * This method firstly checks
5482  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5483  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5484  * an exception is thrown too.
5485  * 
5486  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5487  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
5488  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5489  */
5490 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
5491 {
5492   if(code.empty())
5493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5494   std::size_t sz=code.size();
5495   std::size_t n=sz/3;
5496   if(sz%3!=0)
5497     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5498   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5499   int nb=0;
5500   bool isNoPflUsed=true;
5501   for(std::size_t i=0;i<n;i++)
5502     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5503       {
5504         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5505         nb+=code[3*i+1];
5506         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5507           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5508         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5509       }
5510   if(types.size()!=n)
5511     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5512   if(isNoPflUsed)
5513     {
5514       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5515         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5516       if(types.size()==_types.size())
5517         return 0;
5518     }
5519   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5520   ret->alloc(nb,1);
5521   int *retPtr=ret->getPointer();
5522   const int *connI=_nodal_connec_index->begin();
5523   const int *conn=_nodal_connec->begin();
5524   int nbOfCells=getNumberOfCells();
5525   const int *i=connI;
5526   int kk=0;
5527   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5528     {
5529       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
5530       int offset=(int)std::distance(connI,i);
5531       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
5532       int nbOfCellsOfCurType=(int)std::distance(i,j);
5533       if(code[3*kk+2]==-1)
5534         for(int k=0;k<nbOfCellsOfCurType;k++)
5535           *retPtr++=k+offset;
5536       else
5537         {
5538           int idInIdsPerType=code[3*kk+2];
5539           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
5540             {
5541               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
5542               if(zePfl)
5543                 {
5544                   zePfl->checkAllocated();
5545                   if(zePfl->getNumberOfComponents()==1)
5546                     {
5547                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5548                         {
5549                           if(*k>=0 && *k<nbOfCellsOfCurType)
5550                             *retPtr=(*k)+offset;
5551                           else
5552                             {
5553                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5554                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5555                               throw INTERP_KERNEL::Exception(oss.str());
5556                             }
5557                         }
5558                     }
5559                   else
5560                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5561                 }
5562               else
5563                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5564             }
5565           else
5566             {
5567               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5568               oss << " should be in [0," << idsPerType.size() << ") !";
5569               throw INTERP_KERNEL::Exception(oss.str());
5570             }
5571         }
5572       i=j;
5573     }
5574   return ret.retn();
5575 }
5576
5577 /*!
5578  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5579  * 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.
5580  * 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.
5581  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5582  * 
5583  * \param [in] profile
5584  * \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.
5585  * \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,
5586  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5587  * \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.
5588  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5589  * \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
5590  */
5591 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
5592 {
5593   if(!profile)
5594     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5595   if(profile->getNumberOfComponents()!=1)
5596     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5597   checkConnectivityFullyDefined();
5598   const int *conn=_nodal_connec->begin();
5599   const int *connI=_nodal_connec_index->begin();
5600   int nbOfCells=getNumberOfCells();
5601   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5602   std::vector<int> typeRangeVals(1);
5603   for(const int *i=connI;i!=connI+nbOfCells;)
5604     {
5605       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5606       if(std::find(types.begin(),types.end(),curType)!=types.end())
5607         {
5608           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5609         }
5610       types.push_back(curType);
5611       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5612       typeRangeVals.push_back((int)std::distance(connI,i));
5613     }
5614   //
5615   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5616   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5617   MCAuto<DataArrayInt> tmp0=castArr;
5618   MCAuto<DataArrayInt> tmp1=rankInsideCast;
5619   MCAuto<DataArrayInt> tmp2=castsPresent;
5620   //
5621   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5622   code.resize(3*nbOfCastsFinal);
5623   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
5624   std::vector< MCAuto<DataArrayInt> > idsPerType2;
5625   for(int i=0;i<nbOfCastsFinal;i++)
5626     {
5627       int castId=castsPresent->getIJ(i,0);
5628       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
5629       idsInPflPerType2.push_back(tmp3);
5630       code[3*i]=(int)types[castId];
5631       code[3*i+1]=tmp3->getNumberOfTuples();
5632       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5633       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5634         {
5635           tmp4->copyStringInfoFrom(*profile);
5636           idsPerType2.push_back(tmp4);
5637           code[3*i+2]=(int)idsPerType2.size()-1;
5638         }
5639       else
5640         {
5641           code[3*i+2]=-1;
5642         }
5643     }
5644   std::size_t sz2=idsInPflPerType2.size();
5645   idsInPflPerType.resize(sz2);
5646   for(std::size_t i=0;i<sz2;i++)
5647     {
5648       DataArrayInt *locDa=idsInPflPerType2[i];
5649       locDa->incrRef();
5650       idsInPflPerType[i]=locDa;
5651     }
5652   std::size_t sz=idsPerType2.size();
5653   idsPerType.resize(sz);
5654   for(std::size_t i=0;i<sz;i++)
5655     {
5656       DataArrayInt *locDa=idsPerType2[i];
5657       locDa->incrRef();
5658       idsPerType[i]=locDa;
5659     }
5660 }
5661
5662 /*!
5663  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5664  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5665  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5666  * 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.
5667  */
5668 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
5669 {
5670   checkFullyDefined();
5671   nM1LevMesh->checkFullyDefined();
5672   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5674   if(_coords!=nM1LevMesh->getCoords())
5675     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5676   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
5677   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
5678   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5679   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5680   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5681   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5682   tmp->setConnectivity(tmp0,tmp1);
5683   tmp->renumberCells(ret0->begin(),false);
5684   revDesc=tmp->getNodalConnectivity();
5685   revDescIndx=tmp->getNodalConnectivityIndex();
5686   DataArrayInt *ret=0;
5687   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5688     {
5689       int tmp2;
5690       ret->getMaxValue(tmp2);
5691       ret->decrRef();
5692       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5693       throw INTERP_KERNEL::Exception(oss.str());
5694     }
5695   nM1LevMeshIds=ret;
5696   //
5697   revDesc->incrRef();
5698   revDescIndx->incrRef();
5699   ret1->incrRef();
5700   ret0->incrRef();
5701   meshnM1Old2New=ret0;
5702   return ret1;
5703 }
5704
5705 /*!
5706  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5707  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5708  * in "Old to New" mode.
5709  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
5710  *          this array using decrRef() as it is no more needed.
5711  *  \throw If the nodal connectivity of cells is not defined.
5712  */
5713 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5714 {
5715   checkConnectivityFullyDefined();
5716   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
5717   renumberCells(ret->begin(),false);
5718   return ret.retn();
5719 }
5720
5721 /*!
5722  * This methods checks that cells are sorted by their types.
5723  * This method makes asumption (no check) that connectivity is correctly set before calling.
5724  */
5725 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5726 {
5727   checkFullyDefined();
5728   const int *conn=_nodal_connec->begin();
5729   const int *connI=_nodal_connec_index->begin();
5730   int nbOfCells=getNumberOfCells();
5731   std::set<INTERP_KERNEL::NormalizedCellType> types;
5732   for(const int *i=connI;i!=connI+nbOfCells;)
5733     {
5734       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5735       if(types.find(curType)!=types.end())
5736         return false;
5737       types.insert(curType);
5738       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5739     }
5740   return true;
5741 }
5742
5743 /*!
5744  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5745  * The geometric type order is specified by MED file.
5746  * 
5747  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5748  */
5749 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5750 {
5751   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5752 }
5753
5754 /*!
5755  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5756  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5757  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5758  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5759  */
5760 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5761 {
5762   checkFullyDefined();
5763   const int *conn=_nodal_connec->begin();
5764   const int *connI=_nodal_connec_index->begin();
5765   int nbOfCells=getNumberOfCells();
5766   if(nbOfCells==0)
5767     return true;
5768   int lastPos=-1;
5769   std::set<INTERP_KERNEL::NormalizedCellType> sg;
5770   for(const int *i=connI;i!=connI+nbOfCells;)
5771     {
5772       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5773       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
5774       if(isTypeExists!=orderEnd)
5775         {
5776           int pos=(int)std::distance(orderBg,isTypeExists);
5777           if(pos<=lastPos)
5778             return false;
5779           lastPos=pos;
5780           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5781         }
5782       else
5783         {
5784           if(sg.find(curType)==sg.end())
5785             {
5786               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5787               sg.insert(curType);
5788             }
5789           else
5790             return false;
5791         }
5792     }
5793   return true;
5794 }
5795
5796 /*!
5797  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
5798  * 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
5799  * 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'.
5800  */
5801 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
5802 {
5803   checkConnectivityFullyDefined();
5804   int nbOfCells=getNumberOfCells();
5805   const int *conn=_nodal_connec->begin();
5806   const int *connI=_nodal_connec_index->begin();
5807   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
5808   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
5809   tmpa->alloc(nbOfCells,1);
5810   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
5811   tmpb->fillWithZero();
5812   int *tmp=tmpa->getPointer();
5813   int *tmp2=tmpb->getPointer();
5814   for(const int *i=connI;i!=connI+nbOfCells;i++)
5815     {
5816       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
5817       if(where!=orderEnd)
5818         {
5819           int pos=(int)std::distance(orderBg,where);
5820           tmp2[pos]++;
5821           tmp[std::distance(connI,i)]=pos;
5822         }
5823       else
5824         {
5825           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
5826           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
5827           oss << " has a type " << cm.getRepr() << " not in input array of type !";
5828           throw INTERP_KERNEL::Exception(oss.str());
5829         }
5830     }
5831   nbPerType=tmpb.retn();
5832   return tmpa.retn();
5833 }
5834
5835 /*!
5836  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
5837  *
5838  * \return a new object containing the old to new correspondance.
5839  *
5840  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5841  */
5842 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
5843 {
5844   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5845 }
5846
5847 /*!
5848  * 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.
5849  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
5850  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
5851  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
5852  */
5853 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5854 {
5855   DataArrayInt *nbPerType=0;
5856   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
5857   nbPerType->decrRef();
5858   return tmpa->buildPermArrPerLevel();
5859 }
5860
5861 /*!
5862  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
5863  * The number of cells remains unchanged after the call of this method.
5864  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
5865  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
5866  *
5867  * \return the array giving the correspondance old to new.
5868  */
5869 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
5870 {
5871   checkFullyDefined();
5872   computeTypes();
5873   const int *conn=_nodal_connec->begin();
5874   const int *connI=_nodal_connec_index->begin();
5875   int nbOfCells=getNumberOfCells();
5876   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5877   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
5878     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
5879       {
5880         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5881         types.push_back(curType);
5882         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
5883       }
5884   DataArrayInt *ret=DataArrayInt::New();
5885   ret->alloc(nbOfCells,1);
5886   int *retPtr=ret->getPointer();
5887   std::fill(retPtr,retPtr+nbOfCells,-1);
5888   int newCellId=0;
5889   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
5890     {
5891       for(const int *i=connI;i!=connI+nbOfCells;i++)
5892         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
5893           retPtr[std::distance(connI,i)]=newCellId++;
5894     }
5895   renumberCells(retPtr,false);
5896   return ret;
5897 }
5898
5899 /*!
5900  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
5901  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
5902  * This method makes asumption that connectivity is correctly set before calling.
5903  */
5904 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
5905 {
5906   checkConnectivityFullyDefined();
5907   const int *conn=_nodal_connec->begin();
5908   const int *connI=_nodal_connec_index->begin();
5909   int nbOfCells=getNumberOfCells();
5910   std::vector<MEDCouplingUMesh *> ret;
5911   for(const int *i=connI;i!=connI+nbOfCells;)
5912     {
5913       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5914       int beginCellId=(int)std::distance(connI,i);
5915       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
5916       int endCellId=(int)std::distance(connI,i);
5917       int sz=endCellId-beginCellId;
5918       int *cells=new int[sz];
5919       for(int j=0;j<sz;j++)
5920         cells[j]=beginCellId+j;
5921       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
5922       delete [] cells;
5923       ret.push_back(m);
5924     }
5925   return ret;
5926 }
5927
5928 /*!
5929  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
5930  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
5931  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
5932  *
5933  * \return a newly allocated instance, that the caller must manage.
5934  * \throw If \a this contains more than one geometric type.
5935  * \throw If the nodal connectivity of \a this is not fully defined.
5936  * \throw If the internal data is not coherent.
5937  */
5938 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
5939 {
5940   checkConnectivityFullyDefined();
5941   if(_types.size()!=1)
5942     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
5943   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
5944   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
5945   ret->setCoords(getCoords());
5946   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
5947   if(retC)
5948     {
5949       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
5950       retC->setNodalConnectivity(c);
5951     }
5952   else
5953     {
5954       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
5955       if(!retD)
5956         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
5957       DataArrayInt *c=0,*ci=0;
5958       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
5959       MCAuto<DataArrayInt> cs(c),cis(ci);
5960       retD->setNodalConnectivity(cs,cis);
5961     }
5962   return ret.retn();
5963 }
5964
5965 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
5966 {
5967   checkConnectivityFullyDefined();
5968   if(_types.size()!=1)
5969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
5970   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
5971   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5972   if(cm.isDynamic())
5973     {
5974       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
5975       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
5976       throw INTERP_KERNEL::Exception(oss.str());
5977     }
5978   int nbCells=getNumberOfCells();
5979   int typi=(int)typ;
5980   int nbNodesPerCell=(int)cm.getNumberOfNodes();
5981   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
5982   int *outPtr=connOut->getPointer();
5983   const int *conn=_nodal_connec->begin();
5984   const int *connI=_nodal_connec_index->begin();
5985   nbNodesPerCell++;
5986   for(int i=0;i<nbCells;i++,connI++)
5987     {
5988       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
5989         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
5990       else
5991         {
5992           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 << ") !";
5993           throw INTERP_KERNEL::Exception(oss.str());
5994         }
5995     }
5996   return connOut.retn();
5997 }
5998
5999 /*!
6000  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6001  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6002  * \param nodalConn
6003  * \param nodalConnI
6004  */
6005 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
6006 {
6007   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6008   checkConnectivityFullyDefined();
6009   if(_types.size()!=1)
6010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6011   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6012   if(lgth<nbCells)
6013     throw INTERP_KERNEL::Exception(msg0);
6014   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6015   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6016   int *cp(c->getPointer()),*cip(ci->getPointer());
6017   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6018   cip[0]=0;
6019   for(int i=0;i<nbCells;i++,cip++,incip++)
6020     {
6021       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6022       int delta(stop-strt);
6023       if(delta>=1)
6024         {
6025           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6026             cp=std::copy(incp+strt,incp+stop,cp);
6027           else
6028             throw INTERP_KERNEL::Exception(msg0);
6029         }
6030       else
6031         throw INTERP_KERNEL::Exception(msg0);
6032       cip[1]=cip[0]+delta;
6033     }
6034   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6035 }
6036
6037 /*!
6038  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6039  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6040  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6041  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6042  * are not used here to avoid the build of big permutation array.
6043  *
6044  * \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
6045  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6046  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6047  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6048  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6049  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6050  * \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
6051  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6052  */
6053 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6054                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6055                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
6056 {
6057   std::vector<const MEDCouplingUMesh *> ms2;
6058   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6059     if(*it)
6060       {
6061         (*it)->checkConnectivityFullyDefined();
6062         ms2.push_back(*it);
6063       }
6064   if(ms2.empty())
6065     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6066   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6067   int meshDim=ms2[0]->getMeshDimension();
6068   std::vector<const MEDCouplingUMesh *> m1ssm;
6069   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6070   //
6071   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6072   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6073   int fake=0,rk=0;
6074   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6075   ret1->alloc(0,1); ret2->alloc(0,1);
6076   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6077     {
6078       if(meshDim!=(*it)->getMeshDimension())
6079         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6080       if(refCoo!=(*it)->getCoords())
6081         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6082       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6083       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6084       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6085       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6086         {
6087           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6088           m1ssmSingleAuto.push_back(singleCell);
6089           m1ssmSingle.push_back(singleCell);
6090           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6091         }
6092     }
6093   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6094   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6095   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6096   for(std::size_t i=0;i<m1ssm.size();i++)
6097     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6098   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6099   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6100   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6101   return ret0.retn();
6102 }
6103
6104 /*!
6105  * This method returns a newly created DataArrayInt instance.
6106  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6107  */
6108 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
6109 {
6110   checkFullyDefined();
6111   const int *conn=_nodal_connec->begin();
6112   const int *connIndex=_nodal_connec_index->begin();
6113   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6114   for(const int *w=begin;w!=end;w++)
6115     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6116       ret->pushBackSilent(*w);
6117   return ret.retn();
6118 }
6119
6120 /*!
6121  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6122  * are in [0:getNumberOfCells())
6123  */
6124 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
6125 {
6126   checkFullyDefined();
6127   const int *conn=_nodal_connec->begin();
6128   const int *connI=_nodal_connec_index->begin();
6129   int nbOfCells=getNumberOfCells();
6130   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6131   int *tmp=new int[nbOfCells];
6132   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6133     {
6134       int j=0;
6135       for(const int *i=connI;i!=connI+nbOfCells;i++)
6136         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6137           tmp[std::distance(connI,i)]=j++;
6138     }
6139   DataArrayInt *ret=DataArrayInt::New();
6140   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6141   ret->copyStringInfoFrom(*da);
6142   int *retPtr=ret->getPointer();
6143   const int *daPtr=da->begin();
6144   int nbOfElems=da->getNbOfElems();
6145   for(int k=0;k<nbOfElems;k++)
6146     retPtr[k]=tmp[daPtr[k]];
6147   delete [] tmp;
6148   return ret;
6149 }
6150
6151 /*!
6152  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6153  * This method \b works \b for mesh sorted by type.
6154  * cells whose ids is in 'idsPerGeoType' array.
6155  * This method conserves coords and name of mesh.
6156  */
6157 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6158 {
6159   std::vector<int> code=getDistributionOfTypes();
6160   std::size_t nOfTypesInThis=code.size()/3;
6161   int sz=0,szOfType=0;
6162   for(std::size_t i=0;i<nOfTypesInThis;i++)
6163     {
6164       if(code[3*i]!=type)
6165         sz+=code[3*i+1];
6166       else
6167         szOfType=code[3*i+1];
6168     }
6169   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6170     if(*work<0 || *work>=szOfType)
6171       {
6172         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6173         oss << ". It should be in [0," << szOfType << ") !";
6174         throw INTERP_KERNEL::Exception(oss.str());
6175       }
6176   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6177   int *idsPtr=idsTokeep->getPointer();
6178   int offset=0;
6179   for(std::size_t i=0;i<nOfTypesInThis;i++)
6180     {
6181       if(code[3*i]!=type)
6182         for(int j=0;j<code[3*i+1];j++)
6183           *idsPtr++=offset+j;
6184       else
6185         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6186       offset+=code[3*i+1];
6187     }
6188   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6189   ret->copyTinyInfoFrom(this);
6190   return ret.retn();
6191 }
6192
6193 /*!
6194  * This method returns a vector of size 'this->getNumberOfCells()'.
6195  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6196  */
6197 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6198 {
6199   int ncell=getNumberOfCells();
6200   std::vector<bool> ret(ncell);
6201   const int *cI=getNodalConnectivityIndex()->begin();
6202   const int *c=getNodalConnectivity()->begin();
6203   for(int i=0;i<ncell;i++)
6204     {
6205       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6206       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6207       ret[i]=cm.isQuadratic();
6208     }
6209   return ret;
6210 }
6211
6212 /*!
6213  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6214  */
6215 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6216 {
6217   if(other->getType()!=UNSTRUCTURED)
6218     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6219   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6220   return MergeUMeshes(this,otherC);
6221 }
6222
6223 /*!
6224  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6225  * computed by averaging coordinates of cell nodes, so this method is not a right
6226  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6227  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6228  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6229  *          components. The caller is to delete this array using decrRef() as it is
6230  *          no more needed.
6231  *  \throw If the coordinates array is not set.
6232  *  \throw If the nodal connectivity of cells is not defined.
6233  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6234  */
6235 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6236 {
6237   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6238   int spaceDim=getSpaceDimension();
6239   int nbOfCells=getNumberOfCells();
6240   ret->alloc(nbOfCells,spaceDim);
6241   ret->copyStringInfoFrom(*getCoords());
6242   double *ptToFill=ret->getPointer();
6243   const int *nodal=_nodal_connec->begin();
6244   const int *nodalI=_nodal_connec_index->begin();
6245   const double *coor=_coords->begin();
6246   for(int i=0;i<nbOfCells;i++)
6247     {
6248       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6249       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6250       ptToFill+=spaceDim;
6251     }
6252   return ret.retn();
6253 }
6254
6255 /*!
6256  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6257  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
6258  * 
6259  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6260  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6261  * 
6262  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6263  * \throw If \a this is not fully defined (coordinates and connectivity)
6264  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6265  */
6266 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6267 {
6268   checkFullyDefined();
6269   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6270   int spaceDim=getSpaceDimension();
6271   int nbOfCells=getNumberOfCells();
6272   int nbOfNodes=getNumberOfNodes();
6273   ret->alloc(nbOfCells,spaceDim);
6274   double *ptToFill=ret->getPointer();
6275   const int *nodal=_nodal_connec->begin();
6276   const int *nodalI=_nodal_connec_index->begin();
6277   const double *coor=_coords->begin();
6278   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6279     {
6280       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6281       std::fill(ptToFill,ptToFill+spaceDim,0.);
6282       if(type!=INTERP_KERNEL::NORM_POLYHED)
6283         {
6284           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6285             {
6286               if(*conn>=0 && *conn<nbOfNodes)
6287                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6288               else
6289                 {
6290                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6291                   throw INTERP_KERNEL::Exception(oss.str());
6292                 }
6293             }
6294           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6295           if(nbOfNodesInCell>0)
6296             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6297           else
6298             {
6299               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6300               throw INTERP_KERNEL::Exception(oss.str());
6301             }
6302         }
6303       else
6304         {
6305           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6306           s.erase(-1);
6307           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6308             {
6309               if(*it>=0 && *it<nbOfNodes)
6310                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6311               else
6312                 {
6313                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6314                   throw INTERP_KERNEL::Exception(oss.str());
6315                 }
6316             }
6317           if(!s.empty())
6318             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6319           else
6320             {
6321               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6322               throw INTERP_KERNEL::Exception(oss.str());
6323             }
6324         }
6325     }
6326   return ret.retn();
6327 }
6328
6329 /*!
6330  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6331  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6332  * are specified via an array of cell ids. 
6333  *  \warning Validity of the specified cell ids is not checked! 
6334  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6335  *  \param [in] begin - an array of cell ids of interest.
6336  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6337  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6338  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6339  *          caller is to delete this array using decrRef() as it is no more needed. 
6340  *  \throw If the coordinates array is not set.
6341  *  \throw If the nodal connectivity of cells is not defined.
6342  *
6343  *  \if ENABLE_EXAMPLES
6344  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6345  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6346  *  \endif
6347  */
6348 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6349 {
6350   DataArrayDouble *ret=DataArrayDouble::New();
6351   int spaceDim=getSpaceDimension();
6352   int nbOfTuple=(int)std::distance(begin,end);
6353   ret->alloc(nbOfTuple,spaceDim);
6354   double *ptToFill=ret->getPointer();
6355   double *tmp=new double[spaceDim];
6356   const int *nodal=_nodal_connec->begin();
6357   const int *nodalI=_nodal_connec_index->begin();
6358   const double *coor=_coords->begin();
6359   for(const int *w=begin;w!=end;w++)
6360     {
6361       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6362       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6363       ptToFill+=spaceDim;
6364     }
6365   delete [] tmp;
6366   return ret;
6367 }
6368
6369 /*!
6370  * 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".
6371  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6372  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6373  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6374  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6375  * 
6376  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6377  * \throw If spaceDim!=3 or meshDim!=2.
6378  * \throw If connectivity of \a this is invalid.
6379  * \throw If connectivity of a cell in \a this points to an invalid node.
6380  */
6381 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6382 {
6383   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6384   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6385   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6387   ret->alloc(nbOfCells,4);
6388   double *retPtr(ret->getPointer());
6389   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6390   const double *coor(_coords->begin());
6391   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6392     {
6393       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6394       if(nodalI[1]-nodalI[0]>=4)
6395         {
6396           double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6397                         coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6398                         coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}
6399           ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6400                         coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6401                         coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]};
6402           double cc[3]={aa[1]*bb[2]-aa[2]*bb[1],aa[2]*bb[0]-aa[0]*bb[2],aa[0]*bb[1]-aa[1]*bb[0]};
6403           for(int j=0;j<3;j++)
6404             {
6405               int nodeId(nodal[nodalI[0]+1+j]);
6406               if(nodeId>=0 && nodeId<nbOfNodes)
6407                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6408               else
6409                 {
6410                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6411                   throw INTERP_KERNEL::Exception(oss.str());
6412                 }
6413             }
6414           if(sqrt(cc[0]*cc[0]+cc[1]*cc[1]+cc[2]*cc[2])>1e-7)
6415             {
6416               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6417               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6418             }
6419           else
6420             {
6421               if(nodalI[1]-nodalI[0]==4)
6422                 {
6423                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !";
6424                   throw INTERP_KERNEL::Exception(oss.str());
6425                 }
6426               //
6427               double dd[3]={0.,0.,0.};
6428               for(int offset=nodalI[0]+1;offset<nodalI[1];offset++)
6429                 std::transform(coor+3*nodal[offset],coor+3*(nodal[offset]+1),dd,dd,std::plus<double>());
6430               int nbOfNodesInCell(nodalI[1]-nodalI[0]-1);
6431               std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6432               std::copy(dd,dd+3,matrix+4*2);
6433               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6434               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6435             }
6436         }
6437       else
6438         {
6439           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6440           throw INTERP_KERNEL::Exception(oss.str());
6441         }
6442     }
6443   return ret.retn();
6444 }
6445
6446 /*!
6447  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6448  * 
6449  */
6450 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6451 {
6452   if(!da)
6453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6454   da->checkAllocated();
6455   std::string name(da->getName());
6456   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6457   if(name.empty())
6458     ret->setName("Mesh");
6459   ret->setCoords(da);
6460   int nbOfTuples(da->getNumberOfTuples());
6461   MCAuto<DataArrayInt> c(DataArrayInt::New()),cI(DataArrayInt::New());
6462   c->alloc(2*nbOfTuples,1);
6463   cI->alloc(nbOfTuples+1,1);
6464   int *cp(c->getPointer()),*cip(cI->getPointer());
6465   *cip++=0;
6466   for(int i=0;i<nbOfTuples;i++)
6467     {
6468       *cp++=INTERP_KERNEL::NORM_POINT1;
6469       *cp++=i;
6470       *cip++=2*(i+1);
6471     }
6472   ret->setConnectivity(c,cI,true);
6473   return ret.retn();
6474 }
6475
6476 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6477 {
6478   if(!da)
6479     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6480   da->checkAllocated();
6481   std::string name(da->getName());
6482   MCAuto<MEDCouplingUMesh> ret;
6483   {
6484     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6485     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6486     arr->alloc(da->getNumberOfTuples());
6487     tmp->setCoordsAt(0,arr);
6488     ret=tmp->buildUnstructured();
6489   }
6490   ret->setCoords(da);
6491   if(name.empty())
6492     ret->setName("Mesh");
6493   else
6494     ret->setName(name);
6495   return ret;
6496 }
6497
6498 /*!
6499  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6500  * Cells and nodes of
6501  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6502  *  \param [in] mesh1 - the first mesh.
6503  *  \param [in] mesh2 - the second mesh.
6504  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6505  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6506  *          is no more needed.
6507  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6508  *  \throw If the coordinates array is not set in none of the meshes.
6509  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6510  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6511  */
6512 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6513 {
6514   std::vector<const MEDCouplingUMesh *> tmp(2);
6515   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6516   return MergeUMeshes(tmp);
6517 }
6518
6519 /*!
6520  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6521  * Cells and nodes of
6522  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6523  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6524  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6525  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6526  *          is no more needed.
6527  *  \throw If \a a.size() == 0.
6528  *  \throw If \a a[ *i* ] == NULL.
6529  *  \throw If the coordinates array is not set in none of the meshes.
6530  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6531  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6532  */
6533 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6534 {
6535   std::size_t sz=a.size();
6536   if(sz==0)
6537     return MergeUMeshesLL(a);
6538   for(std::size_t ii=0;ii<sz;ii++)
6539     if(!a[ii])
6540       {
6541         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6542         throw INTERP_KERNEL::Exception(oss.str());
6543       }
6544   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6545   std::vector< const MEDCouplingUMesh * > aa(sz);
6546   int spaceDim=-3;
6547   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6548     {
6549       const MEDCouplingUMesh *cur=a[i];
6550       const DataArrayDouble *coo=cur->getCoords();
6551       if(coo)
6552         spaceDim=coo->getNumberOfComponents();
6553     }
6554   if(spaceDim==-3)
6555     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6556   for(std::size_t i=0;i<sz;i++)
6557     {
6558       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6559       aa[i]=bb[i];
6560     }
6561   return MergeUMeshesLL(aa);
6562 }
6563
6564 /*!
6565  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6566  * dimension and sharing the node coordinates array.
6567  * All cells of the first mesh precede all cells of the second mesh
6568  * within the result mesh.
6569  *  \param [in] mesh1 - the first mesh.
6570  *  \param [in] mesh2 - the second mesh.
6571  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6572  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6573  *          is no more needed.
6574  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6575  *  \throw If the meshes do not share the node coordinates array.
6576  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6577  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6578  */
6579 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6580 {
6581   std::vector<const MEDCouplingUMesh *> tmp(2);
6582   tmp[0]=mesh1; tmp[1]=mesh2;
6583   return MergeUMeshesOnSameCoords(tmp);
6584 }
6585
6586 /*!
6587  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6588  * dimension and sharing the node coordinates array.
6589  * All cells of the *i*-th mesh precede all cells of the
6590  * (*i*+1)-th mesh within the result mesh.
6591  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6592  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6593  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6594  *          is no more needed.
6595  *  \throw If \a a.size() == 0.
6596  *  \throw If \a a[ *i* ] == NULL.
6597  *  \throw If the meshes do not share the node coordinates array.
6598  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6599  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6600  */
6601 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6602 {
6603   if(meshes.empty())
6604     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6605   for(std::size_t ii=0;ii<meshes.size();ii++)
6606     if(!meshes[ii])
6607       {
6608         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6609         throw INTERP_KERNEL::Exception(oss.str());
6610       }
6611   const DataArrayDouble *coords=meshes.front()->getCoords();
6612   int meshDim=meshes.front()->getMeshDimension();
6613   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6614   int meshLgth=0;
6615   int meshIndexLgth=0;
6616   for(;iter!=meshes.end();iter++)
6617     {
6618       if(coords!=(*iter)->getCoords())
6619         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6620       if(meshDim!=(*iter)->getMeshDimension())
6621         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6622       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6623       meshIndexLgth+=(*iter)->getNumberOfCells();
6624     }
6625   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
6626   nodal->alloc(meshLgth,1);
6627   int *nodalPtr=nodal->getPointer();
6628   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
6629   nodalIndex->alloc(meshIndexLgth+1,1);
6630   int *nodalIndexPtr=nodalIndex->getPointer();
6631   int offset=0;
6632   for(iter=meshes.begin();iter!=meshes.end();iter++)
6633     {
6634       const int *nod=(*iter)->getNodalConnectivity()->begin();
6635       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
6636       int nbOfCells=(*iter)->getNumberOfCells();
6637       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6638       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6639       if(iter!=meshes.begin())
6640         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6641       else
6642         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6643       offset+=meshLgth2;
6644     }
6645   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6646   ret->setName("merge");
6647   ret->setMeshDimension(meshDim);
6648   ret->setConnectivity(nodal,nodalIndex,true);
6649   ret->setCoords(coords);
6650   return ret;
6651 }
6652
6653 /*!
6654  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6655  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6656  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6657  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6658  * New" mode are returned for each input mesh.
6659  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6660  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6661  *          valid values [0,1,2], see zipConnectivityTraducer().
6662  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
6663  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6664  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6665  *          no more needed.
6666  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6667  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6668  *          is no more needed.
6669  *  \throw If \a meshes.size() == 0.
6670  *  \throw If \a meshes[ *i* ] == NULL.
6671  *  \throw If the meshes do not share the node coordinates array.
6672  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6673  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6674  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6675  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6676  */
6677 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6678 {
6679   //All checks are delegated to MergeUMeshesOnSameCoords
6680   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6681   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6682   corr.resize(meshes.size());
6683   std::size_t nbOfMeshes=meshes.size();
6684   int offset=0;
6685   const int *o2nPtr=o2n->begin();
6686   for(std::size_t i=0;i<nbOfMeshes;i++)
6687     {
6688       DataArrayInt *tmp=DataArrayInt::New();
6689       int curNbOfCells=meshes[i]->getNumberOfCells();
6690       tmp->alloc(curNbOfCells,1);
6691       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6692       offset+=curNbOfCells;
6693       tmp->setName(meshes[i]->getName());
6694       corr[i]=tmp;
6695     }
6696   return ret.retn();
6697 }
6698
6699 /*!
6700  * Makes all given meshes share the nodal connectivity array. The common connectivity
6701  * array is created by concatenating the connectivity arrays of all given meshes. All
6702  * the given meshes must be of the same space dimension but dimension of cells **can
6703  * differ**. This method is particulary useful in MEDLoader context to build a \ref
6704  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6705  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6706  *  \param [in,out] meshes - a vector of meshes to update.
6707  *  \throw If any of \a meshes is NULL.
6708  *  \throw If the coordinates array is not set in any of \a meshes.
6709  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6710  *  \throw If \a meshes are of different space dimension.
6711  */
6712 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6713 {
6714   std::size_t sz=meshes.size();
6715   if(sz==0 || sz==1)
6716     return;
6717   std::vector< const DataArrayDouble * > coords(meshes.size());
6718   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6719   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6720     {
6721       if((*it))
6722         {
6723           (*it)->checkConnectivityFullyDefined();
6724           const DataArrayDouble *coo=(*it)->getCoords();
6725           if(coo)
6726             *it2=coo;
6727           else
6728             {
6729               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6730               oss << " has no coordinate array defined !";
6731               throw INTERP_KERNEL::Exception(oss.str());
6732             }
6733         }
6734       else
6735         {
6736           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6737           oss << " is null !";
6738           throw INTERP_KERNEL::Exception(oss.str());
6739         }
6740     }
6741   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6742   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6743   int offset=(*it)->getNumberOfNodes();
6744   (*it++)->setCoords(res);
6745   for(;it!=meshes.end();it++)
6746     {
6747       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6748       (*it)->setCoords(res);
6749       (*it)->shiftNodeNumbersInConn(offset);
6750       offset+=oldNumberOfNodes;
6751     }
6752 }
6753
6754 /*!
6755  * Merges nodes coincident with a given precision within all given meshes that share
6756  * the nodal connectivity array. The given meshes **can be of different** mesh
6757  * dimension. This method is particulary useful in MEDLoader context to build a \ref
6758  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6759  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
6760  *  \param [in,out] meshes - a vector of meshes to update.
6761  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
6762  *  \throw If any of \a meshes is NULL.
6763  *  \throw If the \a meshes do not share the same node coordinates array.
6764  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6765  */
6766 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
6767 {
6768   if(meshes.empty())
6769     return ;
6770   std::set<const DataArrayDouble *> s;
6771   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6772     {
6773       if(*it)
6774         s.insert((*it)->getCoords());
6775       else
6776         {
6777           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 !";
6778           throw INTERP_KERNEL::Exception(oss.str());
6779         }
6780     }
6781   if(s.size()!=1)
6782     {
6783       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 !";
6784       throw INTERP_KERNEL::Exception(oss.str());
6785     }
6786   const DataArrayDouble *coo=*(s.begin());
6787   if(!coo)
6788     return;
6789   //
6790   DataArrayInt *comm,*commI;
6791   coo->findCommonTuples(eps,-1,comm,commI);
6792   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
6793   int oldNbOfNodes=coo->getNumberOfTuples();
6794   int newNbOfNodes;
6795   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6796   if(oldNbOfNodes==newNbOfNodes)
6797     return ;
6798   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
6799   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6800     {
6801       (*it)->renumberNodesInConn(o2n->begin());
6802       (*it)->setCoords(newCoords);
6803     } 
6804 }
6805
6806
6807 /*!
6808  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
6809  */
6810 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6811 {
6812   std::size_t i, ip1;
6813   double v[3]={0.,0.,0.};
6814   std::size_t sz=std::distance(begin,end);
6815   if(isQuadratic)
6816     sz/=2;
6817   for(i=0;i<sz;i++)
6818     {
6819       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];
6820       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6821       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6822     }
6823   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6824
6825   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
6826   // SEG3 forming a circle):
6827   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
6828     {
6829       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
6830       for(std::size_t j=0;j<sz;j++)
6831         {
6832           if (j%2)  // current point i is quadratic, next point i+1 is standard
6833             {
6834               i = sz+j;
6835               ip1 = (j+1)%sz; // ip1 = "i+1"
6836             }
6837           else      // current point i is standard, next point i+1 is quadratic
6838             {
6839               i = j;
6840               ip1 = j+sz;
6841             }
6842           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
6843           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
6844           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
6845         }
6846       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
6847     }
6848   return (ret>0.);
6849 }
6850
6851 /*!
6852  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
6853  */
6854 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6855 {
6856   std::vector<std::pair<int,int> > edges;
6857   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6858   const int *bgFace=begin;
6859   for(std::size_t i=0;i<nbOfFaces;i++)
6860     {
6861       const int *endFace=std::find(bgFace+1,end,-1);
6862       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6863       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6864         {
6865           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6866           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6867             return false;
6868           edges.push_back(p1);
6869         }
6870       bgFace=endFace+1;
6871     }
6872   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6873 }
6874
6875 /*!
6876  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
6877  */
6878 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6879 {
6880   double vec0[3],vec1[3];
6881   std::size_t sz=std::distance(begin,end);
6882   if(sz%2!=0)
6883     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6884   int nbOfNodes=(int)sz/2;
6885   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6886   const double *pt0=coords+3*begin[0];
6887   const double *pt1=coords+3*begin[nbOfNodes];
6888   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6889   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
6890 }
6891
6892 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
6893 {
6894   std::size_t sz=std::distance(begin,end);
6895   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
6896   std::size_t nbOfNodes(sz/2);
6897   std::copy(begin,end,(int *)tmp);
6898   for(std::size_t j=1;j<nbOfNodes;j++)
6899     {
6900       begin[j]=tmp[nbOfNodes-j];
6901       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
6902     }
6903 }
6904
6905 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
6906 {
6907   std::size_t sz=std::distance(begin,end);
6908   if(sz!=4)
6909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
6910   double vec0[3],vec1[3];
6911   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
6912   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]; 
6913   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;
6914 }
6915
6916 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
6917 {
6918   std::size_t sz=std::distance(begin,end);
6919   if(sz!=5)
6920     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
6921   double vec0[3];
6922   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
6923   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
6924   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
6925 }
6926
6927 /*!
6928  * 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 ) 
6929  * 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
6930  * a 2D space.
6931  *
6932  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
6933  * \param [in] coords the coordinates with nb of components exactly equal to 3
6934  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
6935  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
6936  * \param [out] res the result is put at the end of the vector without any alteration of the data.
6937  */
6938 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
6939 {
6940   int nbFaces=std::count(begin+1,end,-1)+1;
6941   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
6942   double *vPtr=v->getPointer();
6943   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
6944   double *pPtr=p->getPointer();
6945   const int *stFaceConn=begin+1;
6946   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
6947     {
6948       const int *endFaceConn=std::find(stFaceConn,end,-1);
6949       ComputeVecAndPtOfFace(eps,coords->begin(),stFaceConn,endFaceConn,vPtr,pPtr);
6950       stFaceConn=endFaceConn+1;
6951     }
6952   pPtr=p->getPointer(); vPtr=v->getPointer();
6953   DataArrayInt *comm1=0,*commI1=0;
6954   v->findCommonTuples(eps,-1,comm1,commI1);
6955   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
6956   const int *comm1Ptr=comm1->begin();
6957   const int *commI1Ptr=commI1->begin();
6958   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
6959   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
6960   //
6961   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
6962   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
6963   mm->finishInsertingCells();
6964   //
6965   for(int i=0;i<nbOfGrps1;i++)
6966     {
6967       int vecId=comm1Ptr[commI1Ptr[i]];
6968       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6969       DataArrayInt *comm2=0,*commI2=0;
6970       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
6971       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
6972       const int *comm2Ptr=comm2->begin();
6973       const int *commI2Ptr=commI2->begin();
6974       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
6975       for(int j=0;j<nbOfGrps2;j++)
6976         {
6977           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
6978             {
6979               res->insertAtTheEnd(begin,end);
6980               res->pushBackSilent(-1);
6981             }
6982           else
6983             {
6984               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
6985               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
6986               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
6987               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
6988               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
6989               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
6990               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
6991               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
6992               const int *idsNodePtr=idsNode->begin();
6993               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];
6994               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
6995               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
6996               if(std::abs(norm)>eps)
6997                 {
6998                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
6999                   mm3->rotate(center,vec,angle);
7000                 }
7001               mm3->changeSpaceDimension(2);
7002               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7003               const int *conn4=mm4->getNodalConnectivity()->begin();
7004               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
7005               int nbOfCells=mm4->getNumberOfCells();
7006               for(int k=0;k<nbOfCells;k++)
7007                 {
7008                   int l=0;
7009                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7010                     res->pushBackSilent(idsNodePtr[*work]);
7011                   res->pushBackSilent(-1);
7012                 }
7013             }
7014         }
7015     }
7016   res->popBackSilent();
7017 }
7018
7019 /*!
7020  * 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
7021  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7022  * 
7023  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7024  * \param [in] coords coordinates expected to have 3 components.
7025  * \param [in] begin start of the nodal connectivity of the face.
7026  * \param [in] end end of the nodal connectivity (excluded) of the face.
7027  * \param [out] v the normalized vector of size 3
7028  * \param [out] p the pos of plane
7029  */
7030 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
7031 {
7032   std::size_t nbPoints=std::distance(begin,end);
7033   if(nbPoints<3)
7034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7035   double vec[3]={0.,0.,0.};
7036   std::size_t j=0;
7037   bool refFound=false;
7038   for(;j<nbPoints-1 && !refFound;j++)
7039     {
7040       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7041       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7042       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7043       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7044       if(norm>eps)
7045         {
7046           refFound=true;
7047           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7048         }
7049     }
7050   for(std::size_t i=j;i<nbPoints-1;i++)
7051     {
7052       double curVec[3];
7053       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7054       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7055       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7056       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7057       if(norm<eps)
7058         continue;
7059       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7060       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];
7061       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7062       if(norm>eps)
7063         {
7064           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7065           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7066           return ;
7067         }
7068     }
7069   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7070 }
7071
7072 /*!
7073  * This method tries to obtain a well oriented polyhedron.
7074  * If the algorithm fails, an exception will be thrown.
7075  */
7076 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
7077 {
7078   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7079   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7080   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7081   isPerm[0]=true;
7082   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7083   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7084   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7085   //
7086   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7087     {
7088       bgFace=begin;
7089       std::size_t smthChanged=0;
7090       for(std::size_t i=0;i<nbOfFaces;i++)
7091         {
7092           endFace=std::find(bgFace+1,end,-1);
7093           nbOfEdgesInFace=std::distance(bgFace,endFace);
7094           if(!isPerm[i])
7095             {
7096               bool b;
7097               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7098                 {
7099                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7100                   std::pair<int,int> p2(p1.second,p1.first);
7101                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7102                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7103                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7104                 }
7105               if(isPerm[i])
7106                 { 
7107                   if(!b)
7108                     std::reverse(bgFace+1,endFace);
7109                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7110                     {
7111                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7112                       std::pair<int,int> p2(p1.second,p1.first);
7113                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7114                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7115                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7116                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7117                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7118                       if(it!=edgesOK.end())
7119                         {
7120                           edgesOK.erase(it);
7121                           edgesFinished.push_back(p1);
7122                         }
7123                       else
7124                         edgesOK.push_back(p1);
7125                     }
7126                 }
7127             }
7128           bgFace=endFace+1;
7129         }
7130       if(smthChanged==0)
7131         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7132     }
7133   if(!edgesOK.empty())
7134     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7135   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7136     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7137       bgFace=begin;
7138       for(std::size_t i=0;i<nbOfFaces;i++)
7139         {
7140           endFace=std::find(bgFace+1,end,-1);
7141           std::reverse(bgFace+1,endFace);
7142           bgFace=endFace+1;
7143         }
7144     }
7145 }
7146
7147
7148 /*!
7149  * This method makes the assumption spacedimension == meshdimension == 2.
7150  * This method works only for linear cells.
7151  * 
7152  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7153  */
7154 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
7155 {
7156   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7158   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7159   int oldNbOfNodes(skin->getNumberOfNodes());
7160   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
7161   int nbOfNodesExpected(skin->getNumberOfNodes());
7162   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7163   int nbCells(skin->getNumberOfCells());
7164   if(nbCells==nbOfNodesExpected)
7165     return buildUnionOf2DMeshLinear(skin,n2o);
7166   else if(2*nbCells==nbOfNodesExpected)
7167     return buildUnionOf2DMeshQuadratic(skin,n2o);
7168   else
7169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7170 }
7171
7172 /*!
7173  * This method makes the assumption spacedimension == meshdimension == 3.
7174  * This method works only for linear cells.
7175  * 
7176  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7177  */
7178 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
7179 {
7180   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7181     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7182   MCAuto<MEDCouplingUMesh> m=computeSkin();
7183   const int *conn=m->getNodalConnectivity()->begin();
7184   const int *connI=m->getNodalConnectivityIndex()->begin();
7185   int nbOfCells=m->getNumberOfCells();
7186   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7187   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7188   if(nbOfCells<1)
7189     return ret.retn();
7190   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7191   for(int i=1;i<nbOfCells;i++)
7192     {
7193       *work++=-1;
7194       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7195     }
7196   return ret.retn();
7197 }
7198
7199 /*!
7200  * \brief Creates a graph of cell neighbors
7201  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7202  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7203  *  For example
7204  *  - index:  0 3 5 6 6
7205  *  - value:  1 2 3 2 3 3
7206  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7207  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7208  */
7209 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7210 {
7211   checkConnectivityFullyDefined();
7212
7213   int meshDim = this->getMeshDimension();
7214   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
7215   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
7216   this->getReverseNodalConnectivity(revConn,indexr);
7217   const int* indexr_ptr=indexr->begin();
7218   const int* revConn_ptr=revConn->begin();
7219
7220   const MEDCoupling::DataArrayInt* index;
7221   const MEDCoupling::DataArrayInt* conn;
7222   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7223   index=this->getNodalConnectivityIndex();
7224   int nbCells=this->getNumberOfCells();
7225   const int* index_ptr=index->begin();
7226   const int* conn_ptr=conn->begin();
7227
7228   //creating graph arcs (cell to cell relations)
7229   //arcs are stored in terms of (index,value) notation
7230   // 0 3 5 6 6
7231   // 1 2 3 2 3 3
7232   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7233   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7234
7235   //warning here one node have less than or equal effective number of cell with it
7236   //but cell could have more than effective nodes
7237   //because other equals nodes in other domain (with other global inode)
7238   std::vector <int> cell2cell_index(nbCells+1,0);
7239   std::vector <int> cell2cell;
7240   cell2cell.reserve(3*nbCells);
7241
7242   for (int icell=0; icell<nbCells;icell++)
7243     {
7244       std::map<int,int > counter;
7245       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7246         {
7247           int inode=conn_ptr[iconn];
7248           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7249             {
7250               int icell2=revConn_ptr[iconnr];
7251               std::map<int,int>::iterator iter=counter.find(icell2);
7252               if (iter!=counter.end()) (iter->second)++;
7253               else counter.insert(std::make_pair(icell2,1));
7254             }
7255         }
7256       for (std::map<int,int>::const_iterator iter=counter.begin();
7257            iter!=counter.end(); iter++)
7258         if (iter->second >= meshDim)
7259           {
7260             cell2cell_index[icell+1]++;
7261             cell2cell.push_back(iter->first);
7262           }
7263     }
7264   indexr->decrRef();
7265   revConn->decrRef();
7266   cell2cell_index[0]=0;
7267   for (int icell=0; icell<nbCells;icell++)
7268     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7269
7270   //filling up index and value to create skylinearray structure
7271   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7272   return array;
7273 }
7274
7275
7276 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7277 {
7278   int nbOfCells=getNumberOfCells();
7279   if(nbOfCells<=0)
7280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7281   ofs << "  <" << getVTKDataSetType() << ">\n";
7282   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7283   ofs << "      <PointData>\n" << pointData << std::endl;
7284   ofs << "      </PointData>\n";
7285   ofs << "      <CellData>\n" << cellData << std::endl;
7286   ofs << "      </CellData>\n";
7287   ofs << "      <Points>\n";
7288   if(getSpaceDimension()==3)
7289     _coords->writeVTK(ofs,8,"Points",byteData);
7290   else
7291     {
7292       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7293       coo->writeVTK(ofs,8,"Points",byteData);
7294     }
7295   ofs << "      </Points>\n";
7296   ofs << "      <Cells>\n";
7297   const int *cPtr=_nodal_connec->begin();
7298   const int *cIPtr=_nodal_connec_index->begin();
7299   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7300   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7301   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7302   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7303   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7304   int szFaceOffsets=0,szConn=0;
7305   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7306     {
7307       *w2=cPtr[cIPtr[i]];
7308       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7309         {
7310           *w1=-1;
7311           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7312           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7313         }
7314       else
7315         {
7316           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7317           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7318           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7319           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7320           w4=std::copy(c.begin(),c.end(),w4);
7321         }
7322     }
7323   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
7324   types->writeVTK(ofs,8,"UInt8","types",byteData);
7325   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
7326   if(szFaceOffsets!=0)
7327     {//presence of Polyhedra
7328       connectivity->reAlloc(szConn);
7329       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
7330       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7331       w1=faces->getPointer();
7332       for(int i=0;i<nbOfCells;i++)
7333         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7334           {
7335             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7336             *w1++=nbFaces;
7337             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7338             for(int j=0;j<nbFaces;j++)
7339               {
7340                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7341                 *w1++=(int)std::distance(w6,w5);
7342                 w1=std::copy(w6,w5,w1);
7343                 w6=w5+1;
7344               }
7345           }
7346       faces->writeVTK(ofs,8,"Int32","faces",byteData);
7347     }
7348   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
7349   ofs << "      </Cells>\n";
7350   ofs << "    </Piece>\n";
7351   ofs << "  </" << getVTKDataSetType() << ">\n";
7352 }
7353
7354 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7355 {
7356   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7357   if(_mesh_dim==-2)
7358     { stream << " Not set !"; return ; }
7359   stream << " Mesh dimension : " << _mesh_dim << ".";
7360   if(_mesh_dim==-1)
7361     return ;
7362   if(!_coords)
7363     { stream << " No coordinates set !"; return ; }
7364   if(!_coords->isAllocated())
7365     { stream << " Coordinates set but not allocated !"; return ; }
7366   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7367   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7368   if(!_nodal_connec_index)
7369     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7370   if(!_nodal_connec_index->isAllocated())
7371     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7372   int lgth=_nodal_connec_index->getNumberOfTuples();
7373   int cpt=_nodal_connec_index->getNumberOfComponents();
7374   if(cpt!=1 || lgth<1)
7375     return ;
7376   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7377 }
7378
7379 std::string MEDCouplingUMesh::getVTKDataSetType() const
7380 {
7381   return std::string("UnstructuredGrid");
7382 }
7383
7384 std::string MEDCouplingUMesh::getVTKFileExtension() const
7385 {
7386   return std::string("vtu");
7387 }
7388
7389
7390
7391 /**
7392  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7393  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7394  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7395  * The caller is to deal with the resulting DataArrayInt.
7396  *  \throw If the coordinate array is not set.
7397  *  \throw If the nodal connectivity of the cells is not defined.
7398  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7399  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7400  *
7401  * \sa DataArrayInt::sortEachPairToMakeALinkedList
7402  */
7403 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
7404 {
7405   checkFullyDefined();
7406   if(getMeshDimension()!=1)
7407     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7408
7409   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7410   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
7411   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
7412   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7413   const int *d(_d->begin()), *dI(_dI->begin());
7414   const int *rD(_rD->begin()), *rDI(_rDI->begin());
7415   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
7416   const int * dsi(_dsi->begin());
7417   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
7418   m_points=0;
7419   if (dsii->getNumberOfTuples())
7420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7421
7422   int nc(getNumberOfCells());
7423   MCAuto<DataArrayInt> result(DataArrayInt::New());
7424   result->alloc(nc,1);
7425
7426   // set of edges not used so far
7427   std::set<int> edgeSet;
7428   for (int i=0; i<nc; edgeSet.insert(i), i++);
7429
7430   int startSeg=0;
7431   int newIdx=0;
7432   // while we have points with only one neighbor segments
7433   do
7434     {
7435       std::list<int> linePiece;
7436       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7437       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7438         {
7439           // Fill the list forward (resp. backward) from the start segment:
7440           int activeSeg = startSeg;
7441           int prevPointId = -20;
7442           int ptId;
7443           while (!edgeSet.empty())
7444             {
7445               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7446                 {
7447                   if (direction==0)
7448                     linePiece.push_back(activeSeg);
7449                   else
7450                     linePiece.push_front(activeSeg);
7451                   edgeSet.erase(activeSeg);
7452                 }
7453
7454               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7455               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7456               if (dsi[ptId] == 1) // hitting the end of the line
7457                 break;
7458               prevPointId = ptId;
7459               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7460               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7461             }
7462         }
7463       // Done, save final piece into DA:
7464       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7465       newIdx += linePiece.size();
7466
7467       // identify next valid start segment (one which is not consumed)
7468       if(!edgeSet.empty())
7469         startSeg = *(edgeSet.begin());
7470     }
7471   while (!edgeSet.empty());
7472   return result.retn();
7473 }
7474
7475 /**
7476  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7477  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7478  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7479  * a minimal creation of new nodes is wanted.
7480  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7481  * nodes if a SEG3 is split without information of middle.
7482  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7483  * avoid to have a non conform mesh.
7484  *
7485  * \return int - the number of new nodes created (in most of cases 0).
7486  * 
7487  * \throw If \a this is not coherent.
7488  * \throw If \a this has not spaceDim equal to 2.
7489  * \throw If \a this has not meshDim equal to 2.
7490  * \throw If some subcells needed to be split are orphan.
7491  * \sa MEDCouplingUMesh::conformize2D
7492  */
7493 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
7494 {
7495   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7496     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7497   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7498   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7499     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7500   if(midOpt==0 && midOptI==0)
7501     {
7502       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7503       return 0;
7504     }
7505   else if(midOpt!=0 && midOptI!=0)
7506     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7507   else
7508     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7509 }
7510
7511 /*!
7512  * 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
7513  * 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
7514  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7515  * 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
7516  * 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.
7517  * 
7518  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7519  */
7520 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
7521 {
7522   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7523   if(sz>=4)
7524     {
7525       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7526       if(cm.getDimension()==2)
7527         {
7528           const int *node=nodalConnBg+1;
7529           int startNode=*node++;
7530           double refX=coords[2*startNode];
7531           for(;node!=nodalConnEnd;node++)
7532             {
7533               if(coords[2*(*node)]<refX)
7534                 {
7535                   startNode=*node;
7536                   refX=coords[2*startNode];
7537                 }
7538             }
7539           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7540           refX=1e300;
7541           double tmp1;
7542           double tmp2[2];
7543           double angle0=-M_PI/2;
7544           //
7545           int nextNode=-1;
7546           int prevNode=-1;
7547           double resRef;
7548           double angleNext=0.;
7549           while(nextNode!=startNode)
7550             {
7551               nextNode=-1;
7552               resRef=1e300;
7553               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7554                 {
7555                   if(*node!=tmpOut.back() && *node!=prevNode)
7556                     {
7557                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7558                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7559                       double res;
7560                       if(angleM<=angle0)
7561                         res=angle0-angleM;
7562                       else
7563                         res=angle0-angleM+2.*M_PI;
7564                       if(res<resRef)
7565                         {
7566                           nextNode=*node;
7567                           resRef=res;
7568                           angleNext=angleM;
7569                         }
7570                     }
7571                 }
7572               if(nextNode!=startNode)
7573                 {
7574                   angle0=angleNext-M_PI;
7575                   if(angle0<-M_PI)
7576                     angle0+=2*M_PI;
7577                   prevNode=tmpOut.back();
7578                   tmpOut.push_back(nextNode);
7579                 }
7580             }
7581           std::vector<int> tmp3(2*(sz-1));
7582           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7583           std::copy(nodalConnBg+1,nodalConnEnd,it);
7584           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7585             {
7586               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7587               return false;
7588             }
7589           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7590             {
7591               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7592               return false;
7593             }
7594           else
7595             {
7596               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7597               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7598               return true;
7599             }
7600         }
7601       else
7602         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7603     }
7604   else
7605     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7606 }
7607
7608 /*!
7609  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7610  * 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.
7611  * 
7612  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7613  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7614  * \param [in,out] arr array in which the remove operation will be done.
7615  * \param [in,out] arrIndx array in the remove operation will modify
7616  * \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])
7617  * \return true if \b arr and \b arrIndx have been modified, false if not.
7618  */
7619 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
7620 {
7621   if(!arrIndx || !arr)
7622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7623   if(offsetForRemoval<0)
7624     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7625   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7626   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7627   int *arrIPtr=arrIndx->getPointer();
7628   *arrIPtr++=0;
7629   int previousArrI=0;
7630   const int *arrPtr=arr->begin();
7631   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7632   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7633     {
7634       if(*arrIPtr-previousArrI>offsetForRemoval)
7635         {
7636           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
7637             {
7638               if(s.find(*work)==s.end())
7639                 arrOut.push_back(*work);
7640             }
7641         }
7642       previousArrI=*arrIPtr;
7643       *arrIPtr=(int)arrOut.size();
7644     }
7645   if(arr->getNumberOfTuples()==(int)arrOut.size())
7646     return false;
7647   arr->alloc((int)arrOut.size(),1);
7648   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
7649   return true;
7650 }
7651
7652 /*!
7653  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7654  * (\ref numbering-indirect).
7655  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
7656  * The selection of extraction is done standardly in new2old format.
7657  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7658  *
7659  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7660  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7661  * \param [in] arrIn arr origin array from which the extraction will be done.
7662  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7663  * \param [out] arrOut the resulting array
7664  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7665  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
7666  */
7667 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7668                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7669 {
7670   if(!arrIn || !arrIndxIn)
7671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
7672   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7673   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7674     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
7675   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
7676   const int *arrInPtr=arrIn->begin();
7677   const int *arrIndxPtr=arrIndxIn->begin();
7678   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7679   if(nbOfGrps<0)
7680     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7681   int maxSizeOfArr=arrIn->getNumberOfTuples();
7682   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7683   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7684   arrIo->alloc((int)(sz+1),1);
7685   const int *idsIt=idsOfSelectBg;
7686   int *work=arrIo->getPointer();
7687   *work++=0;
7688   int lgth=0;
7689   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
7690     {
7691       if(*idsIt>=0 && *idsIt<nbOfGrps)
7692         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
7693       else
7694         {
7695           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7696           throw INTERP_KERNEL::Exception(oss.str());
7697         }
7698       if(lgth>=work[-1])
7699         *work=lgth;
7700       else
7701         {
7702           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
7703           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
7704           throw INTERP_KERNEL::Exception(oss.str());
7705         }
7706     }
7707   arro->alloc(lgth,1);
7708   work=arro->getPointer();
7709   idsIt=idsOfSelectBg;
7710   for(std::size_t i=0;i<sz;i++,idsIt++)
7711     {
7712       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
7713         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
7714       else
7715         {
7716           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
7717           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7718           throw INTERP_KERNEL::Exception(oss.str());
7719         }
7720     }
7721   arrOut=arro.retn();
7722   arrIndexOut=arrIo.retn();
7723 }
7724
7725 /*!
7726  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
7727  * (\ref numbering-indirect).
7728  * 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 ).
7729  * The selection of extraction is done standardly in new2old format.
7730  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
7731  *
7732  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
7733  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
7734  * \param [in] idsOfSelectStep
7735  * \param [in] arrIn arr origin array from which the extraction will be done.
7736  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7737  * \param [out] arrOut the resulting array
7738  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7739  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
7740  */
7741 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7742                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7743 {
7744   if(!arrIn || !arrIndxIn)
7745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
7746   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
7747   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
7748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
7749   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
7750   const int *arrInPtr=arrIn->begin();
7751   const int *arrIndxPtr=arrIndxIn->begin();
7752   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
7753   if(nbOfGrps<0)
7754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
7755   int maxSizeOfArr=arrIn->getNumberOfTuples();
7756   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7757   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7758   arrIo->alloc((int)(sz+1),1);
7759   int idsIt=idsOfSelectStart;
7760   int *work=arrIo->getPointer();
7761   *work++=0;
7762   int lgth=0;
7763   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
7764     {
7765       if(idsIt>=0 && idsIt<nbOfGrps)
7766         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
7767       else
7768         {
7769           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
7770           throw INTERP_KERNEL::Exception(oss.str());
7771         }
7772       if(lgth>=work[-1])
7773         *work=lgth;
7774       else
7775         {
7776           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
7777           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
7778           throw INTERP_KERNEL::Exception(oss.str());
7779         }
7780     }
7781   arro->alloc(lgth,1);
7782   work=arro->getPointer();
7783   idsIt=idsOfSelectStart;
7784   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
7785     {
7786       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
7787         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
7788       else
7789         {
7790           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
7791           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
7792           throw INTERP_KERNEL::Exception(oss.str());
7793         }
7794     }
7795   arrOut=arro.retn();
7796   arrIndexOut=arrIo.retn();
7797 }
7798
7799 /*!
7800  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7801  * 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
7802  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7803  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7804  *
7805  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7806  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7807  * \param [in] arrIn arr origin array from which the extraction will be done.
7808  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7809  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
7810  * \param [in] srcArrIndex index array of \b srcArr
7811  * \param [out] arrOut the resulting array
7812  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7813  * 
7814  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
7815  */
7816 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7817                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7818                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7819 {
7820   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
7822   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7823   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7824   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7825   std::vector<bool> v(nbOfTuples,true);
7826   int offset=0;
7827   const int *arrIndxInPtr=arrIndxIn->begin();
7828   const int *srcArrIndexPtr=srcArrIndex->begin();
7829   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7830     {
7831       if(*it>=0 && *it<nbOfTuples)
7832         {
7833           v[*it]=false;
7834           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
7835         }
7836       else
7837         {
7838           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7839           throw INTERP_KERNEL::Exception(oss.str());
7840         }
7841     }
7842   srcArrIndexPtr=srcArrIndex->begin();
7843   arrIo->alloc(nbOfTuples+1,1);
7844   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
7845   const int *arrInPtr=arrIn->begin();
7846   const int *srcArrPtr=srcArr->begin();
7847   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
7848   int *arroPtr=arro->getPointer();
7849   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
7850     {
7851       if(v[ii])
7852         {
7853           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
7854           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
7855         }
7856       else
7857         {
7858           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
7859           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
7860           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
7861         }
7862     }
7863   arrOut=arro.retn();
7864   arrIndexOut=arrIo.retn();
7865 }
7866
7867 /*!
7868  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7869  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
7870  *
7871  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
7872  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
7873  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
7874  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7875  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
7876  * \param [in] srcArrIndex index array of \b srcArr
7877  * 
7878  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
7879  */
7880 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
7881                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
7882 {
7883   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
7885   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7886   const int *arrIndxInPtr=arrIndxIn->begin();
7887   const int *srcArrIndexPtr=srcArrIndex->begin();
7888   int *arrInOutPtr=arrInOut->getPointer();
7889   const int *srcArrPtr=srcArr->begin();
7890   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
7891     {
7892       if(*it>=0 && *it<nbOfTuples)
7893         {
7894           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
7895             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
7896           else
7897             {
7898               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] !";
7899               throw INTERP_KERNEL::Exception(oss.str());
7900             }
7901         }
7902       else
7903         {
7904           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
7905           throw INTERP_KERNEL::Exception(oss.str());
7906         }
7907     }
7908 }
7909
7910 /*!
7911  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7912  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7913  * 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]].
7914  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7915  * A negative value in \b arrIn means that it is ignored.
7916  * 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.
7917  * 
7918  * \param [in] arrIn arr origin array from which the extraction will be done.
7919  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7920  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7921  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
7922  */
7923 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
7924 {
7925   int seed=0,nbOfDepthPeelingPerformed=0;
7926   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
7927 }
7928
7929 /*!
7930  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7931  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7932  * 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]].
7933  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7934  * A negative value in \b arrIn means that it is ignored.
7935  * 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.
7936  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
7937  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
7938  * \param [in] arrIn arr origin array from which the extraction will be done.
7939  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7940  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
7941  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
7942  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7943  * \sa MEDCouplingUMesh::partitionBySpreadZone
7944  */
7945 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
7946 {
7947   nbOfDepthPeelingPerformed=0;
7948   if(!arrIndxIn)
7949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
7950   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7951   if(nbOfTuples<=0)
7952     {
7953       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
7954       return ret;
7955     }
7956   //
7957   std::vector<bool> fetched(nbOfTuples,false);
7958   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
7959 }
7960
7961
7962 /*!
7963  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
7964  * 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
7965  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
7966  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
7967  *
7968  * \param [in] start begin of set of ids of the input extraction (included)
7969  * \param [in] end end of set of ids of the input extraction (excluded)
7970  * \param [in] step step of the set of ids in range mode.
7971  * \param [in] arrIn arr origin array from which the extraction will be done.
7972  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7973  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
7974  * \param [in] srcArrIndex index array of \b srcArr
7975  * \param [out] arrOut the resulting array
7976  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
7977  * 
7978  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
7979  */
7980 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
7981                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
7982                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
7983 {
7984   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
7985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
7986   MCAuto<DataArrayInt> arro=DataArrayInt::New();
7987   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
7988   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7989   int offset=0;
7990   const int *arrIndxInPtr=arrIndxIn->begin();
7991   const int *srcArrIndexPtr=srcArrIndex->begin();
7992   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
7993   int it=start;
7994   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
7995     {
7996       if(it>=0 && it<nbOfTuples)
7997         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
7998       else
7999         {
8000           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8001           throw INTERP_KERNEL::Exception(oss.str());
8002         }
8003     }
8004   srcArrIndexPtr=srcArrIndex->begin();
8005   arrIo->alloc(nbOfTuples+1,1);
8006   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8007   const int *arrInPtr=arrIn->begin();
8008   const int *srcArrPtr=srcArr->begin();
8009   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8010   int *arroPtr=arro->getPointer();
8011   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8012     {
8013       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8014       if(pos<0)
8015         {
8016           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8017           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8018         }
8019       else
8020         {
8021           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8022           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8023         }
8024     }
8025   arrOut=arro.retn();
8026   arrIndexOut=arrIo.retn();
8027 }
8028
8029 /*!
8030  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8031  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8032  *
8033  * \param [in] start begin of set of ids of the input extraction (included)
8034  * \param [in] end end of set of ids of the input extraction (excluded)
8035  * \param [in] step step of the set of ids in range mode.
8036  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8037  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8038  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8039  * \param [in] srcArrIndex index array of \b srcArr
8040  * 
8041  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8042  */
8043 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8044                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
8045 {
8046   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8047     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
8048   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8049   const int *arrIndxInPtr=arrIndxIn->begin();
8050   const int *srcArrIndexPtr=srcArrIndex->begin();
8051   int *arrInOutPtr=arrInOut->getPointer();
8052   const int *srcArrPtr=srcArr->begin();
8053   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
8054   int it=start;
8055   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8056     {
8057       if(it>=0 && it<nbOfTuples)
8058         {
8059           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8060             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8061           else
8062             {
8063               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8064               throw INTERP_KERNEL::Exception(oss.str());
8065             }
8066         }
8067       else
8068         {
8069           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8070           throw INTERP_KERNEL::Exception(oss.str());
8071         }
8072     }
8073 }
8074
8075 /*!
8076  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8077  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8078  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8079  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8080  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8081  * 
8082  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8083  */
8084 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
8085 {
8086   checkFullyDefined();
8087   int mdim=getMeshDimension();
8088   int spaceDim=getSpaceDimension();
8089   if(mdim!=spaceDim)
8090     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8091   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8092   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8093   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
8094   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8095   ret->setCoords(getCoords());
8096   ret->allocateCells((int)partition.size());
8097   //
8098   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8099     {
8100       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8101       MCAuto<DataArrayInt> cell;
8102       switch(mdim)
8103       {
8104         case 2:
8105           cell=tmp->buildUnionOf2DMesh();
8106           break;
8107         case 3:
8108           cell=tmp->buildUnionOf3DMesh();
8109           break;
8110         default:
8111           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8112       }
8113
8114       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
8115     }
8116   //
8117   ret->finishInsertingCells();
8118   return ret.retn();
8119 }
8120
8121 /*!
8122  * This method partitions \b this into contiguous zone.
8123  * This method only needs a well defined connectivity. Coordinates are not considered here.
8124  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8125  */
8126 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
8127 {
8128   DataArrayInt *neigh=0,*neighI=0;
8129   computeNeighborsOfCells(neigh,neighI);
8130   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8131   return PartitionBySpreadZone(neighAuto,neighIAuto);
8132 }
8133
8134 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
8135 {
8136   if(!arrIn || !arrIndxIn)
8137     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
8138   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8139   int nbOfTuples(arrIndxIn->getNumberOfTuples());
8140   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8141     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8142   int nbOfCellsCur(nbOfTuples-1);
8143   std::vector<DataArrayInt *> ret;
8144   if(nbOfCellsCur<=0)
8145     return ret;
8146   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8147   std::vector< MCAuto<DataArrayInt> > ret2;
8148   int seed=0;
8149   while(seed<nbOfCellsCur)
8150     {
8151       int nbOfPeelPerformed=0;
8152       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8153       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8154     }
8155   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8156     ret.push_back((*it).retn());
8157   return ret;
8158 }
8159
8160 /*!
8161  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8162  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8163  *
8164  * \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.
8165  * \return a newly allocated DataArrayInt to be managed by the caller.
8166  * \throw In case of \a code has not the right format (typically of size 3*n)
8167  */
8168 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
8169 {
8170   MCAuto<DataArrayInt> ret=DataArrayInt::New();
8171   std::size_t nb=code.size()/3;
8172   if(code.size()%3!=0)
8173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8174   ret->alloc((int)nb,2);
8175   int *retPtr=ret->getPointer();
8176   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8177     {
8178       retPtr[0]=code[3*i+2];
8179       retPtr[1]=code[3*i+2]+code[3*i+1];
8180     }
8181   return ret.retn();
8182 }
8183
8184 /*!
8185  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8186  * All cells in \a this are expected to be linear 3D cells.
8187  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8188  * It leads to an increase to number of cells.
8189  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8190  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
8191  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8192  *
8193  * \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.
8194  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8195  * \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. 
8196  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
8197  *          an id of old cell producing it. The caller is to delete this array using
8198  *         decrRef() as it is no more needed.
8199  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8200  *
8201  * \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
8202  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8203  * 
8204  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8205  * \throw If \a this is not fully constituted with linear 3D cells.
8206  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8207  */
8208 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
8209 {
8210   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8211   checkConnectivityFullyDefined();
8212   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8213     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8214   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
8215   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8216   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
8217   int *retPt(ret->getPointer());
8218   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
8219   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8220   const int *oldc(_nodal_connec->begin());
8221   const int *oldci(_nodal_connec_index->begin());
8222   const double *coords(_coords->begin());
8223   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
8224     {
8225       std::vector<int> a; std::vector<double> b;
8226       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8227       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
8228       const int *aa(&a[0]);
8229       if(!b.empty())
8230         {
8231           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
8232             if(*it<0)
8233               *it=(-(*(it))-1+nbNodes);
8234           addPts->insertAtTheEnd(b.begin(),b.end());
8235           nbNodes+=(int)b.size()/3;
8236         }
8237       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8238         newConn->insertAtTheEnd(aa,aa+4);
8239     }
8240   if(!addPts->empty())
8241     {
8242       addPts->rearrange(3);
8243       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8244       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8245       ret0->setCoords(addPts);
8246     }
8247   else
8248     {
8249       nbOfAdditionalPoints=0;
8250       ret0->setCoords(getCoords());
8251     }
8252   ret0->setNodalConnectivity(newConn);
8253   //
8254   ret->computeOffsetsFull();
8255   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8256   return ret0.retn();
8257 }
8258
8259 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8260     _own_cell(true),_cell_id(-1),_nb_cell(0)
8261 {
8262   if(mesh)
8263     {
8264       mesh->incrRef();
8265       _nb_cell=mesh->getNumberOfCells();
8266     }
8267 }
8268
8269 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8270 {
8271   if(_mesh)
8272     _mesh->decrRef();
8273   if(_own_cell)
8274     delete _cell;
8275 }
8276
8277 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8278     _own_cell(false),_cell_id(bg-1),
8279     _nb_cell(end)
8280 {
8281   if(mesh)
8282     mesh->incrRef();
8283 }
8284
8285 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8286 {
8287   _cell_id++;
8288   if(_cell_id<_nb_cell)
8289     {
8290       _cell->next();
8291       return _cell;
8292     }
8293   else
8294     return 0;
8295 }
8296
8297 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8298 {
8299   if(_mesh)
8300     _mesh->incrRef();
8301 }
8302
8303 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8304 {
8305   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8306 }
8307
8308 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8309 {
8310   if(_mesh)
8311     _mesh->decrRef();
8312 }
8313
8314 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8315     _itc(itc),
8316     _bg(bg),_end(end)
8317 {
8318   if(_mesh)
8319     _mesh->incrRef();
8320 }
8321
8322 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8323 {
8324   if(_mesh)
8325     _mesh->decrRef();
8326 }
8327
8328 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8329 {
8330   return _type;
8331 }
8332
8333 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8334 {
8335   return _end-_bg;
8336 }
8337
8338 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8339 {
8340   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8341 }
8342
8343 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8344 {
8345   if(mesh)
8346     {
8347       mesh->incrRef();
8348       _nb_cell=mesh->getNumberOfCells();
8349     }
8350 }
8351
8352 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8353 {
8354   if(_mesh)
8355     _mesh->decrRef();
8356   delete _cell;
8357 }
8358
8359 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8360 {
8361   const int *c=_mesh->getNodalConnectivity()->begin();
8362   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
8363   if(_cell_id<_nb_cell)
8364     {
8365       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8366       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
8367       int startId=_cell_id;
8368       _cell_id+=nbOfElems;
8369       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8370     }
8371   else
8372     return 0;
8373 }
8374
8375 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8376 {
8377   if(mesh)
8378     {
8379       _conn=mesh->getNodalConnectivity()->getPointer();
8380       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8381     }
8382 }
8383
8384 void MEDCouplingUMeshCell::next()
8385 {
8386   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8387     {
8388       _conn+=_conn_lgth;
8389       _conn_indx++;
8390     }
8391   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8392 }
8393
8394 std::string MEDCouplingUMeshCell::repr() const
8395 {
8396   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8397     {
8398       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8399       oss << " : ";
8400       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8401       return oss.str();
8402     }
8403   else
8404     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8405 }
8406
8407 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8408 {
8409   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8410     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8411   else
8412     return INTERP_KERNEL::NORM_ERROR;
8413 }
8414
8415 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8416 {
8417   lgth=_conn_lgth;
8418   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8419     return _conn;
8420   else
8421     return 0;
8422 }