Salome HOME
Merge last changes for 0021856: [CEA 663] Documenting API of MEDCoupling and MEDLoade...
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
28 #include "BBTree.txx"
29 #include "SplitterTetra.hxx"
30 #include "DirectedBoundingBox.hxx"
31 #include "InterpKernelMeshQuality.hxx"
32 #include "InterpKernelCellSimplify.hxx"
33 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
34 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
35 #include "InterpKernelAutoPtr.hxx"
36 #include "InterpKernelGeo2DNode.hxx"
37 #include "InterpKernelGeo2DEdgeLin.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
40
41 #include <sstream>
42 #include <fstream>
43 #include <numeric>
44 #include <cstring>
45 #include <limits>
46 #include <list>
47
48 using namespace ParaMEDMEM;
49
50 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
51
52 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 };
53
54 MEDCouplingUMesh *MEDCouplingUMesh::New()
55 {
56   return new MEDCouplingUMesh;
57 }
58
59 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
60 {
61   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
62   ret->setName(meshName);
63   ret->setMeshDimension(meshDim);
64   return ret;
65 }
66
67 /*!
68  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
69  * between \a this and the new mesh.
70  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
71  *          delete this mesh using decrRef() as it is no more needed. 
72  */
73 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
74 {
75   return clone(true);
76 }
77
78 /*!
79  * Returns a new MEDCouplingMesh which is a copy of \a this one.
80  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
81  * this mesh are shared by the new mesh.
82  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
83  *          delete this mesh using decrRef() as it is no more needed. 
84  */
85 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
86 {
87   return new MEDCouplingUMesh(*this,recDeepCpy);
88 }
89
90 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
91 {
92   std::size_t ret=0;
93   if(_nodal_connec)
94     ret+=_nodal_connec->getHeapMemorySize();
95   if(_nodal_connec_index)
96     ret+=_nodal_connec_index->getHeapMemorySize();
97   return MEDCouplingPointSet::getHeapMemorySize()+ret;
98 }
99
100 void MEDCouplingUMesh::updateTime() const
101 {
102   MEDCouplingPointSet::updateTime();
103   if(_nodal_connec)
104     {
105       updateTimeWith(*_nodal_connec);
106     }
107   if(_nodal_connec_index)
108     {
109       updateTimeWith(*_nodal_connec_index);
110     }
111 }
112
113 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
114 {
115 }
116
117 /*!
118  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
119  * then \a this mesh is most probably is writable, exchangeable and available for most
120  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
121  * this method to check that all is in order with \a this mesh.
122  *  \throw If the mesh dimension is not set.
123  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
124  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
125  *  \throw If the connectivity data array has more than one component.
126  *  \throw If the connectivity data array has a named component.
127  *  \throw If the connectivity index data array has more than one component.
128  *  \throw If the connectivity index data array has a named component.
129  */
130 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
131 {
132   if(_mesh_dim<-1)
133    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
134   if(_mesh_dim!=-1)
135     MEDCouplingPointSet::checkCoherency();
136   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
137     {
138       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
139         {
140           std::ostringstream message;
141           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
142           throw INTERP_KERNEL::Exception(message.str().c_str());
143         }
144     }
145   if(_nodal_connec)
146     {
147       if(_nodal_connec->getNumberOfComponents()!=1)
148         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
149       if(_nodal_connec->getInfoOnComponent(0)!="")
150         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
151     }
152   if(_nodal_connec_index)
153     {
154       if(_nodal_connec_index->getNumberOfComponents()!=1)
155         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
156       if(_nodal_connec_index->getInfoOnComponent(0)!="")
157         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
158     }
159 }
160
161 /*!
162  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
163  * then \a this mesh is most probably is writable, exchangeable and available for all
164  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
165  * method thoroughly checks the nodal connectivity.
166  *  \param [in] eps - a not used parameter.
167  *  \throw If the mesh dimension is not set.
168  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
169  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
170  *  \throw If the connectivity data array has more than one component.
171  *  \throw If the connectivity data array has a named component.
172  *  \throw If the connectivity index data array has more than one component.
173  *  \throw If the connectivity index data array has a named component.
174  *  \throw If number of nodes defining an element does not correspond to the type of element.
175  *  \throw If the nodal connectivity includes an invalid node id.
176  */
177 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
178 {
179   checkCoherency();
180   if(_mesh_dim==-1)
181     return ;
182   int meshDim=getMeshDimension();
183   int nbOfNodes=getNumberOfNodes();
184   int nbOfCells=getNumberOfCells();
185   const int *ptr=_nodal_connec->getConstPointer();
186   const int *ptrI=_nodal_connec_index->getConstPointer();
187   for(int i=0;i<nbOfCells;i++)
188     {
189       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
190       if((int)cm.getDimension()!=meshDim)
191         {
192           std::ostringstream oss;
193           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
194           throw INTERP_KERNEL::Exception(oss.str().c_str());
195         }
196       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
197       if(!cm.isDynamic())
198         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
199           {
200             std::ostringstream oss;
201             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
202             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
203             throw INTERP_KERNEL::Exception(oss.str().c_str());
204           }
205       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
206         {
207           int nodeId=*w;
208           if(nodeId>=0)
209             {
210               if(nodeId>=nbOfNodes)
211                 {
212                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
213                   throw INTERP_KERNEL::Exception(oss.str().c_str());
214                 }
215             }
216           else if(nodeId<-1)
217             {
218               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
219               throw INTERP_KERNEL::Exception(oss.str().c_str());
220             }
221           else
222             {
223               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
224                 {
225                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
226                   throw INTERP_KERNEL::Exception(oss.str().c_str());
227                 }
228             }
229         }
230     }
231 }
232
233
234 /*!
235  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
236  * then \a this mesh is most probably is writable, exchangeable and available for all
237  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
238  *  \param [in] eps - a not used parameter.
239  *  \throw If the mesh dimension is not set.
240  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
241  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
242  *  \throw If the connectivity data array has more than one component.
243  *  \throw If the connectivity data array has a named component.
244  *  \throw If the connectivity index data array has more than one component.
245  *  \throw If the connectivity index data array has a named component.
246  *  \throw If number of nodes defining an element does not correspond to the type of element.
247  *  \throw If the nodal connectivity includes an invalid node id.
248  */
249 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
250 {
251   checkCoherency1(eps);
252 }
253
254 /*!
255  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
256  * elements contained in the mesh. For more info on the mesh dimension see
257  * \ref MEDCouplingUMeshPage.
258  *  \param [in] meshDim - a new mesh dimension.
259  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
260  */
261 void MEDCouplingUMesh::setMeshDimension(int meshDim)
262 {
263   if(meshDim<-1 || meshDim>3)
264     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
265   _mesh_dim=meshDim;
266   declareAsNew();
267 }
268
269 /*!
270  * Allocates memory to store given number of cells.
271  *  \param [in] nbOfCells - number of cell \a this mesh will contain.
272  *
273  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
274  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
275  */
276 void MEDCouplingUMesh::allocateCells(int nbOfCells)
277 {
278   if(_nodal_connec_index)
279     {
280       _nodal_connec_index->decrRef();
281     }
282   if(_nodal_connec)
283     {
284       _nodal_connec->decrRef();
285     }
286   _nodal_connec_index=DataArrayInt::New();
287   _nodal_connec_index->reserve(nbOfCells+1);
288   _nodal_connec_index->pushBackSilent(0);
289   _nodal_connec=DataArrayInt::New();
290   _nodal_connec->reserve(2*nbOfCells);
291   _types.clear();
292   declareAsNew();
293 }
294
295 /*!
296  * Appends a cell to the connectivity array. For deeper understanding what is
297  * happening see \ref MEDCouplingUMeshNodalConnectivity.
298  *  \param [in] type - type of cell to add.
299  *  \param [in] size - number of nodes constituting this cell.
300  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
301  * 
302  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
303  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
304  */
305 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
306 {
307   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
308   if(_nodal_connec_index==0)
309     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
310   if((int)cm.getDimension()==_mesh_dim)
311     {
312       if(!cm.isDynamic())
313         if(size!=(int)cm.getNumberOfNodes())
314           {
315             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
316             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
317             throw INTERP_KERNEL::Exception(oss.str().c_str());
318           }
319       int idx=_nodal_connec_index->back();
320       int val=idx+size+1;
321       _nodal_connec_index->pushBackSilent(val);
322       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
323       _types.insert(type);
324     }
325   else
326     {
327       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
328       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
329       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
330       throw INTERP_KERNEL::Exception(oss.str().c_str());
331     }
332 }
333
334 /*!
335  * Compacts data arrays to release unused memory. This method is to be called after
336  * finishing cell insertion using \a this->insertNextCell().
337  * 
338  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
339  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
340  */
341 void MEDCouplingUMesh::finishInsertingCells()
342 {
343   _nodal_connec->pack();
344   _nodal_connec_index->pack();
345   _nodal_connec->declareAsNew();
346   _nodal_connec_index->declareAsNew();
347   updateTime();
348 }
349
350 /*!
351  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
352  * Useful for python users.
353  */
354 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
355 {
356   return new MEDCouplingUMeshCellIterator(this);
357 }
358
359 /*!
360  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
361  * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
362  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
363  * Useful for python users.
364  */
365 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
366 {
367   if(!checkConsecutiveCellTypes())
368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
369   return new MEDCouplingUMeshCellByTypeEntry(this);
370 }
371
372 /*!
373  * Returns a set of all cell types available in \a this mesh.
374  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
375  */
376 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
377 {
378   return _types;
379 }
380
381 /*!
382  * This method is a method that compares 'this' and 'other'.
383  * This method compares \b all attributes, even names and component names.
384  */
385 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
386 {
387   if(!other)
388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
389   std::ostringstream oss; oss.precision(15);
390   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
391   if(!otherC)
392     {
393       reason="mesh given in input is not castable in MEDCouplingUMesh !";
394       return false;
395     }
396   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
397     return false;
398   if(_mesh_dim!=otherC->_mesh_dim)
399     {
400       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
401       reason=oss.str();
402       return false;
403     }
404   if(_types!=otherC->_types)
405     {
406       oss << "umesh geometric type mismatch :\nThis geometric types are :";
407       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
408         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
409       oss << "\nOther geometric types are :";
410       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
411         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
412       reason=oss.str();
413       return false;
414     }
415   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
416     if(_nodal_connec==0 || otherC->_nodal_connec==0)
417       {
418         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
419         return false;
420       }
421   if(_nodal_connec!=otherC->_nodal_connec)
422     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
423       {
424         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
425         return false;
426       }
427   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
428     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
429       {
430         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
431         return false;
432       }
433   if(_nodal_connec_index!=otherC->_nodal_connec_index)
434     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
435       {
436         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
437         return false;
438       }
439   return true;
440 }
441
442 /*!
443  * Checks if data arrays of this mesh (node coordinates, nodal
444  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
445  * not considered.
446  *  \param [in] other - the mesh to compare with.
447  *  \param [in] prec - precision value used to compare node coordinates.
448  *  \return bool - \a true if the two meshes are same.
449  */
450 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
451 {
452   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
453   if(!otherC)
454     return false;
455   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
456     return false;
457   if(_mesh_dim!=otherC->_mesh_dim)
458     return false;
459   if(_types!=otherC->_types)
460     return false;
461   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
462     if(_nodal_connec==0 || otherC->_nodal_connec==0)
463       return false;
464   if(_nodal_connec!=otherC->_nodal_connec)
465     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
466       return false;
467   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
468     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
469       return false;
470   if(_nodal_connec_index!=otherC->_nodal_connec_index)
471     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
472       return false;
473   return true;
474 }
475
476 /*!
477  * Checks if \a this and \a other meshes are geometrically equivalent, else an
478  * exception is thrown. The meshes are
479  * considered equivalent if (1) \a this mesh contains the same nodes as the \a other
480  * mesh (with a specified precision) and (2) \a this mesh contains the same cells as
481  * the \a other mesh (with use of a specified cell comparison technique). The mapping 
482  * from \a other to \a this for nodes and cells is returned via out parameters.
483  *  \param [in] other - the mesh to compare with.
484  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See meaning of
485  *         each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
486  *  \param [in] prec - the precision used to compare nodes of the two meshes.
487  *  \param [out] cellCor - a cell permutation array in "Old to New" mode. The caller is
488  *         to delete this array using decrRef() as it is no more needed.
489  *  \param [out] nodeCor - a node permutation array in "Old to New" mode. The caller is
490  *         to delete this array using decrRef() as it is no more needed.
491  *  \throw If the two meshes do not match.
492  *
493  *  \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
494  *  \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
495  */
496 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
497                                             DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
498 {
499   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
500   if(!otherC)
501     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
502   MEDCouplingMesh::checkFastEquivalWith(other,prec);
503   if(_types!=otherC->_types)
504     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
505   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
506   bool areNodesMerged;
507   int newNbOfNodes;
508   int oldNbOfNodes=getNumberOfNodes();
509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
510   //mergeNodes
511   if(!areNodesMerged)
512     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
513   const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
514   if(pt!=da->getConstPointer()+da->getNbOfElems())
515     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
516   m->renumberNodes(da->getConstPointer(),newNbOfNodes);
517   //
518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
519   da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
520   
521   //
522   da=m->zipConnectivityTraducer(cellCompPol);
523   int nbCells=getNumberOfCells();
524   int maxId=-1;
525   if(nbCells!=0)
526     maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+nbCells);
527   pt=std::find_if(da->getConstPointer()+nbCells,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
528   if(pt!=da->getConstPointer()+da->getNbOfElems())
529     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
530   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(nbCells,da->getNbOfElems(),1);
531   nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
532   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
533 }
534
535 /*!
536  * Checks if \a this and \a other meshes are geometrically equivalent, else an
537  * exception is thrown. The meshes are considered equivalent if (1) they share one
538  * node coordinates array and (2) they contain the same cells (with use of a specified
539  * cell comparison technique). The mapping from cells of the \a other to ones of \a this 
540  * is returned via an out parameter.
541  *  \param [in] other - the mesh to compare with.
542  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
543  *         each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
544  *  \param [in] prec - a not used parameter.
545  *  \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
546  *         to delete this array using decrRef() as it is no more needed.
547  *  \throw If the two meshes do not match.
548  *
549  * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
550  * \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
551  */
552 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
553                                                        DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
554 {
555   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
556   if(!otherC)
557     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
558   MEDCouplingMesh::checkFastEquivalWith(other,prec);
559   if(_types!=otherC->_types)
560     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
561   if(_coords!=otherC->_coords)
562     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
563   std::vector<const MEDCouplingUMesh *> ms(2);
564   ms[0]=this;
565   ms[1]=otherC;
566   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
568   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
569   const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
570   if(pt!=da->getConstPointer()+da->getNbOfElems())
571     {
572       throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
573     }
574   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
575   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
576 }
577
578 /*!
579  * Checks if \a this and \a other meshes are geometrically equivalent with high
580  * probability, else an exception is thrown. The meshes are considered equivalent if
581  * (1) meshes contain the same number of nodes and the same number of elements of the
582  * same types (2) three cells of the two meshes (first, last and middle) are based
583  * on coincident nodes (with a specified precision).
584  *  \param [in] other - the mesh to compare with.
585  *  \param [in] prec - the precision used to compare nodes of the two meshes.
586  *  \throw If the two meshes do not match.
587  */
588 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
589 {
590   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
591   if(!otherC)
592     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
593   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
594   int nbOfCells=getNumberOfCells();
595   if(nbOfCells<1)
596     return ;
597   bool status=true;
598   status&=areCellsFrom2MeshEqual(otherC,0,prec);
599   status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
600   status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
601   if(!status)
602     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
603 }
604
605 /*!
606  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
607  * cells each node belongs to.
608  * \warning For speed reasons, this method does not check if node ids in the nodal
609  *          connectivity correspond to the size of node coordinates array.
610  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
611  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
612  *        dividing cell ids in \a revNodal into groups each referring to one
613  *        node. Its every element (except the last one) is an index pointing to the
614  *         first id of a group of cells. For example cells sharing the node #1 are 
615  *        described by following range of indices: 
616  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
617  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
618  *        Number of cells sharing the *i*-th node is
619  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
620  * \throw If the coordinates array is not set.
621  * \throw If the nodal connectivity of cells is not defined.
622  * 
623  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
624  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
625  */
626 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
627 {
628   checkFullyDefined();
629   int nbOfNodes=getNumberOfNodes();
630   int *revNodalIndxPtr=new int[nbOfNodes+1];
631   revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
632   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
633   const int *conn=_nodal_connec->getConstPointer();
634   const int *connIndex=_nodal_connec_index->getConstPointer();
635   int nbOfCells=getNumberOfCells();
636   int nbOfEltsInRevNodal=0;
637   for(int eltId=0;eltId<nbOfCells;eltId++)
638     {
639       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
640       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
641       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
642         if(*iter>=0)//for polyhedrons
643           {
644             nbOfEltsInRevNodal++;
645             revNodalIndxPtr[(*iter)+1]++;
646           }
647     }
648   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
649   int *revNodalPtr=new int[nbOfEltsInRevNodal];
650   revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
651   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
652   for(int eltId=0;eltId<nbOfCells;eltId++)
653     {
654       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
655       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
656       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
657         if(*iter>=0)//for polyhedrons
658           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
659     }
660 }
661
662 /// @cond INTERNAL
663
664 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
665 {
666   return id;
667 }
668
669 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
670 {
671   if(!compute)
672     return id+1;
673   else
674     {
675       if(cm.getOrientationStatus(nb,conn1,conn2))
676         return id+1;
677       else
678         return -(id+1);
679     }
680 }
681
682 class MinusOneSonsGenerator
683 {
684 public:
685   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
686   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
687   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
688   static const int DELTA=1;
689 private:
690   const INTERP_KERNEL::CellModel& _cm;
691 };
692
693 class MinusOneSonsGeneratorBiQuadratic
694 {
695 public:
696   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
697   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
698   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
699   static const int DELTA=1;
700 private:
701   const INTERP_KERNEL::CellModel& _cm;
702 };
703
704 class MinusTwoSonsGenerator
705 {
706 public:
707   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
708   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
709   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
710   static const int DELTA=2;
711 private:
712   const INTERP_KERNEL::CellModel& _cm;
713 };
714
715 /// @endcond
716
717 /*!
718  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
719  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
720  * describing correspondence between cells of \a this and the result meshes are
721  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
722  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
723  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
724  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
725  * \warning For speed reasons, this method does not check if node ids in the nodal
726  *          connectivity correspond to the size of node coordinates array.
727  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
728  *          to write this mesh to the MED file, its cells must be sorted using
729  *          sortCellsInMEDFileFrmt().
730  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
731  *         each cell of \a this mesh.
732  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
733  *        dividing cell ids in \a desc into groups each referring to one
734  *        cell of \a this mesh. Its every element (except the last one) is an index
735  *        pointing to the first id of a group of cells. For example cells of the
736  *        result mesh bounding the cell #1 of \a this mesh are described by following
737  *        range of indices:
738  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
739  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
740  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
741  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
742  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
743  *         by each cell of the result mesh.
744  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
745  *        in the result mesh,
746  *        dividing cell ids in \a revDesc into groups each referring to one
747  *        cell of the result mesh the same way as \a descIndx divides \a desc.
748  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
749  *        delete this mesh using decrRef() as it is no more needed.
750  *  \throw If the coordinates array is not set.
751  *  \throw If the nodal connectivity of cells is node defined.
752  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
753  *         revDescIndx == NULL.
754  * 
755  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
756  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
757  * \sa buildDescendingConnectivity2()
758  */
759 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
760 {
761   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
762 }
763
764 /*!
765  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
766  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
767  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
768  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
769  * \sa MEDCouplingUMesh::buildDescendingConnectivity
770  */
771 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
772 {
773   checkFullyDefined();
774   if(getMeshDimension()!=3)
775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
776   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
777 }
778
779 /*!
780  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
781  * this->getMeshDimension(), that bound cells of \a this mesh. In
782  * addition arrays describing correspondence between cells of \a this and the result
783  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
784  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
785  *  mesh. This method differs from buildDescendingConnectivity() in that apart
786  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
787  * result meshes. So a positive id means that order of nodes in corresponding cells
788  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
789  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
790  * i.e. cell ids are one-based.
791  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
792  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
793  * \warning For speed reasons, this method does not check if node ids in the nodal
794  *          connectivity correspond to the size of node coordinates array.
795  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
796  *          to write this mesh to the MED file, its cells must be sorted using
797  *          sortCellsInMEDFileFrmt().
798  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
799  *         each cell of \a this mesh.
800  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
801  *        dividing cell ids in \a desc into groups each referring to one
802  *        cell of \a this mesh. Its every element (except the last one) is an index
803  *        pointing to the first id of a group of cells. For example cells of the
804  *        result mesh bounding the cell #1 of \a this mesh are described by following
805  *        range of indices:
806  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
807  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
808  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
809  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
810  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
811  *         by each cell of the result mesh.
812  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
813  *        in the result mesh,
814  *        dividing cell ids in \a revDesc into groups each referring to one
815  *        cell of the result mesh the same way as \a descIndx divides \a desc.
816  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
817  *        shares the node coordinates array with \a this mesh. The caller is to
818  *        delete this mesh using decrRef() as it is no more needed.
819  *  \throw If the coordinates array is not set.
820  *  \throw If the nodal connectivity of cells is node defined.
821  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
822  *         revDescIndx == NULL.
823  * 
824  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
825  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
826  * \sa buildDescendingConnectivity()
827  */
828 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
829 {
830   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
831 }
832
833 /*!
834  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
835  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
836  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
837  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
838  *
839  * \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
840  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841  * \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.
842  */
843 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
844 {
845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
849   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
850   meshDM1=0;
851   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
852 }
853
854 /*!
855  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
856  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
857  * excluding a set of meshdim-1 cells in input descending connectivity.
858  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
859  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
860  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
861  *
862  * \param [in] desc descending connectivity array.
863  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
864  * \param [in] revDesc reverse descending connectivity array.
865  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
866  * \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
867  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
868  * \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.
869  */
870 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
871                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
872 {
873   if(!desc || !descIndx || !revDesc || !revDescIndx)
874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
875   const int *descPtr=desc->getConstPointer();
876   const int *descIPtr=descIndx->getConstPointer();
877   const int *revDescPtr=revDesc->getConstPointer();
878   const int *revDescIPtr=revDescIndx->getConstPointer();
879   //
880   int nbCells=descIndx->getNumberOfTuples()-1;
881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
883   int *out1Ptr=out1->getPointer();
884   *out1Ptr++=0;
885   out0->reserve(desc->getNumberOfTuples());
886   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
887     {
888       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
889         {
890           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
891           s.erase(i);
892           out0->insertAtTheEnd(s.begin(),s.end());
893         }
894       *out1Ptr=out0->getNumberOfTuples();
895     }
896   neighbors=out0.retn();
897   neighborsIndx=out1.retn();
898 }
899
900 /// @cond INTERNAL
901
902 /*!
903  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
904  * For speed reasons no check of this will be done.
905  */
906 template<class SonsGenerator>
907 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
908 {
909   if(!desc || !descIndx || !revDesc || !revDescIndx)
910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
911   checkConnectivityFullyDefined();
912   int nbOfCells=getNumberOfCells();
913   int nbOfNodes=getNumberOfNodes();
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
915   int *revNodalIndxPtr=revNodalIndx->getPointer();
916   const int *conn=_nodal_connec->getConstPointer();
917   const int *connIndex=_nodal_connec_index->getConstPointer();
918   std::string name="Mesh constituent of "; name+=getName();
919   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
920   ret->setCoords(getCoords());
921   ret->allocateCells(2*nbOfCells);
922   descIndx->alloc(nbOfCells+1,1);
923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
924   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
925   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
926     {
927       int pos=connIndex[eltId];
928       int posP1=connIndex[eltId+1];
929       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
930       SonsGenerator sg(cm);
931       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
932       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
933       for(unsigned i=0;i<nbOfSons;i++)
934         {
935           INTERP_KERNEL::NormalizedCellType cmsId;
936           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
937           for(unsigned k=0;k<nbOfNodesSon;k++)
938             if(tmp[k]>=0)
939               revNodalIndxPtr[tmp[k]+1]++;
940           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
941           revDesc2->pushBackSilent(eltId);
942         }
943       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
944     }
945   int nbOfCellsM1=ret->getNumberOfCells();
946   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
947   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
948   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
949   int *revNodalPtr=revNodal->getPointer();
950   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
951   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
952   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
953     {
954       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
955       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
956       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
957         if(*iter>=0)//for polyhedrons
958           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
959     }
960   //
961   DataArrayInt *commonCells=0,*commonCellsI=0;
962   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
964   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
965   int newNbOfCellsM1=-1;
966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
967                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
968   std::vector<bool> isImpacted(nbOfCellsM1,false);
969   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
970     for(int work2=work[0];work2!=work[1];work2++)
971       isImpacted[commonCellsPtr[work2]]=true;
972   const int *o2nM1Ptr=o2nM1->getConstPointer();
973   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
974   const int *n2oM1Ptr=n2oM1->getConstPointer();
975   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
976   ret2->copyTinyInfoFrom(this);
977   desc->alloc(descIndx->back(),1);
978   int *descPtr=desc->getPointer();
979   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
980   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
981     {
982       if(!isImpacted[i])
983         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
984       else
985         {
986           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
987             {
988               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
989               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
990             }
991           else
992             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
993         }
994     }
995   revDesc->reserve(newNbOfCellsM1);
996   revDescIndx->alloc(newNbOfCellsM1+1,1);
997   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
998   const int *revDesc2Ptr=revDesc2->getConstPointer();
999   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1000     {
1001       int oldCellIdM1=n2oM1Ptr[i];
1002       if(!isImpacted[oldCellIdM1])
1003         {
1004           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1005           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1006         }
1007       else
1008         {
1009           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1010             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1011           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1012           commonCellsIPtr++;
1013         }
1014     }
1015   //
1016   return ret2.retn();
1017 }
1018
1019 struct MEDCouplingAccVisit
1020 {
1021   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1022   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1023   int _new_nb_of_nodes;
1024 };
1025
1026 /// @endcond
1027
1028 /*!
1029  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1030  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1031  * array of cell ids. Pay attention that after conversion all algorithms work slower
1032  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1033  * conversion due presence of invalid ids in the array of cells to convert, as a
1034  * result \a this mesh contains some already converted elements. In this case the 2D
1035  * mesh remains valid but 3D mesh becomes \b inconsistent!
1036  *  \warning This method can significantly modify the order of geometric types in \a this,
1037  *          hence, to write this mesh to the MED file, its cells must be sorted using
1038  *          sortCellsInMEDFileFrmt().
1039  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1040  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1041  *         cellIdsToConvertBg.
1042  *  \throw If the coordinates array is not set.
1043  *  \throw If the nodal connectivity of cells is node defined.
1044  *  \throw If dimension of \a this mesh is not either 2 or 3.
1045  *
1046  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1047  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1048  */
1049 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1050 {
1051   checkFullyDefined();
1052   int dim=getMeshDimension();
1053   if(dim<2 || dim>3)
1054     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1055   int nbOfCells=getNumberOfCells();
1056   if(dim==2)
1057     {
1058       const int *connIndex=_nodal_connec_index->getConstPointer();
1059       int *conn=_nodal_connec->getPointer();
1060       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1061         {
1062           if(*iter>=0 && *iter<nbOfCells)
1063             {
1064               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1065               if(!cm.isDynamic())
1066                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1067               else
1068                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1069             }
1070           else
1071             {
1072               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1073               oss << " in range [0," << nbOfCells << ") !";
1074               throw INTERP_KERNEL::Exception(oss.str().c_str());
1075             }
1076         }
1077     }
1078   else
1079     {
1080       int *connIndex=_nodal_connec_index->getPointer();
1081       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1082       const int *connOld=_nodal_connec->getConstPointer();
1083       int connOldLgth=_nodal_connec->getNbOfElems();
1084       std::vector<int> connNew(connOld,connOld+connOldLgth);
1085       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1086         {
1087           if(*iter>=0 && *iter<nbOfCells)
1088             {
1089               int pos=connIndex[*iter];
1090               int posP1=connIndex[(*iter)+1];
1091               int lgthOld=posP1-pos-1;
1092               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1093               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1094               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1095               int *tmp=new int[nbOfFaces*lgthOld];
1096               int *work=tmp;
1097               for(int j=0;j<(int)nbOfFaces;j++)
1098                 {
1099                   INTERP_KERNEL::NormalizedCellType type;
1100                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1101                   work+=offset;
1102                   *work++=-1;
1103                 }
1104               std::size_t newLgth=std::distance(tmp,work)-1;
1105               std::size_t delta=newLgth-lgthOld;
1106               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1107               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1108               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1109               delete [] tmp;
1110             }
1111           else
1112             {
1113               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1114               oss << " in range [0," << nbOfCells << ") !";
1115               throw INTERP_KERNEL::Exception(oss.str().c_str());
1116             }
1117         }
1118       _nodal_connec->alloc((int)connNew.size(),1);
1119       int *newConnPtr=_nodal_connec->getPointer();
1120       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1121     }
1122   computeTypes();
1123 }
1124
1125 /*!
1126  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1127  * polyhedrons (if \a this is a 3D mesh).
1128  *  \warning As this method is purely for user-friendliness and no optimization is
1129  *          done to avoid construction of a useless vector, this method can be costly
1130  *          in memory.
1131  *  \throw If the coordinates array is not set.
1132  *  \throw If the nodal connectivity of cells is node defined.
1133  *  \throw If dimension of \a this mesh is not either 2 or 3.
1134  */
1135 void MEDCouplingUMesh::convertAllToPoly()
1136 {
1137   int nbOfCells=getNumberOfCells();
1138   std::vector<int> cellIds(nbOfCells);
1139   for(int i=0;i<nbOfCells;i++)
1140     cellIds[i]=i;
1141   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1142 }
1143
1144 /*!
1145  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1146  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1147  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1148  * base facet of the volume and the second half of nodes describes an opposite facet
1149  * having the same number of nodes as the base one. This method converts such
1150  * connectivity to a valid polyhedral format where connectivity of each facet is
1151  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1152  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1153  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1154  * a correct orientation of the first facet of a polyhedron, else orientation of a
1155  * corrected cell is reverse.<br>
1156  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1157  * it releases the user from boring description of polyhedra connectivity in the valid
1158  * format.
1159  *  \throw If \a this->getMeshDimension() != 3.
1160  *  \throw If \a this->getSpaceDimension() != 3.
1161  *  \throw If the nodal connectivity of cells is not defined.
1162  *  \throw If the coordinates array is not set.
1163  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1164  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1165  *
1166  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1167  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1168  */
1169 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1170 {
1171   checkFullyDefined();
1172   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1174   int nbOfCells=getNumberOfCells();
1175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1176   newCi->alloc(nbOfCells+1,1);
1177   int *newci=newCi->getPointer();
1178   const int *ci=_nodal_connec_index->getConstPointer();
1179   const int *c=_nodal_connec->getConstPointer();
1180   newci[0]=0;
1181   for(int i=0;i<nbOfCells;i++)
1182     {
1183       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1184       if(type==INTERP_KERNEL::NORM_POLYHED)
1185         {
1186           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1187             {
1188               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1189               throw INTERP_KERNEL::Exception(oss.str().c_str());
1190             }
1191           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1192           if(n2%2!=0)
1193             {
1194               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 !";
1195               throw INTERP_KERNEL::Exception(oss.str().c_str());
1196             }
1197           int n1=(int)(n2/2);
1198           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)
1199         }
1200       else
1201         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1202     }
1203   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1204   newC->alloc(newci[nbOfCells],1);
1205   int *newc=newC->getPointer();
1206   for(int i=0;i<nbOfCells;i++)
1207     {
1208       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1209       if(type==INTERP_KERNEL::NORM_POLYHED)
1210         {
1211           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1212           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1213           *newc++=-1;
1214           for(std::size_t j=0;j<n1;j++)
1215             {
1216               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1217               newc[n1+5*j]=-1;
1218               newc[n1+5*j+1]=c[ci[i]+1+j];
1219               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1220               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1221               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1222             }
1223           newc+=n1*6;
1224         }
1225       else
1226         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1227     }
1228   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1229   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1230 }
1231
1232
1233 /*!
1234  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1235  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1236  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1237  *          to write this mesh to the MED file, its cells must be sorted using
1238  *          sortCellsInMEDFileFrmt().
1239  * \return \c true if at least one cell has been converted, \c false else. In the
1240  *         last case the nodal connectivity remains unchanged.
1241  * \throw If the coordinates array is not set.
1242  * \throw If the nodal connectivity of cells is not defined.
1243  * \throw If \a this->getMeshDimension() < 0.
1244  */
1245 bool MEDCouplingUMesh::unPolyze()
1246 {
1247   checkFullyDefined();
1248   int mdim=getMeshDimension();
1249   if(mdim<0)
1250     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1251   if(mdim<=1)
1252     return false;
1253   int nbOfCells=getNumberOfCells();
1254   if(nbOfCells<1)
1255     return false;
1256   int initMeshLgth=getMeshLength();
1257   int *conn=_nodal_connec->getPointer();
1258   int *index=_nodal_connec_index->getPointer();
1259   int posOfCurCell=0;
1260   int newPos=0;
1261   int lgthOfCurCell;
1262   bool ret=false;
1263   for(int i=0;i<nbOfCells;i++)
1264     {
1265       lgthOfCurCell=index[i+1]-posOfCurCell;
1266       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1267       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1268       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1269       int newLgth;
1270       if(cm.isDynamic())
1271         {
1272           switch(cm.getDimension())
1273             {
1274             case 2:
1275               {
1276                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1277                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1278                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1279                 break;
1280               }
1281             case 3:
1282               {
1283                 int nbOfFaces,lgthOfPolyhConn;
1284                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1285                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1286                 break;
1287               }
1288             case 1:
1289               {
1290                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1291                 break;
1292               }
1293             }
1294           ret=ret || (newType!=type);
1295           conn[newPos]=newType;
1296           newPos+=newLgth+1;
1297           posOfCurCell=index[i+1];
1298           index[i+1]=newPos;
1299         }
1300       else
1301         {
1302           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1303           newPos+=lgthOfCurCell;
1304           posOfCurCell+=lgthOfCurCell;
1305           index[i+1]=newPos;
1306         }
1307     }
1308   if(newPos!=initMeshLgth)
1309     _nodal_connec->reAlloc(newPos);
1310   if(ret)
1311     computeTypes();
1312   return ret;
1313 }
1314
1315 /*!
1316  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1317  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1318  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1319  *
1320  * \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 
1321  *             precision.
1322  */
1323 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1324 {
1325   checkFullyDefined();
1326   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1327     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1328   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1329   coords->recenterForMaxPrecision(eps);
1330   //
1331   int nbOfCells=getNumberOfCells();
1332   const int *conn=_nodal_connec->getConstPointer();
1333   const int *index=_nodal_connec_index->getConstPointer();
1334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1335   connINew->alloc(nbOfCells+1,1);
1336   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1338   bool changed=false;
1339   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1340     {
1341       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1342         {
1343           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1344           changed=true;
1345         }
1346       else
1347         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1348       *connINewPtr=connNew->getNumberOfTuples();
1349     }
1350   if(changed)
1351     setConnectivity(connNew,connINew,false);
1352 }
1353
1354 /*!
1355  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1356  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1357  * the format of returned DataArrayInt instance.
1358  * 
1359  * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1360  * \sa MEDCouplingUMesh::getNodeIdsInUse
1361  */
1362 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1363 {
1364   checkConnectivityFullyDefined();
1365   int nbOfCells=getNumberOfCells();
1366   const int *connIndex=_nodal_connec_index->getConstPointer();
1367   const int *conn=_nodal_connec->getConstPointer();
1368   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1369   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1370   std::vector<bool> retS(maxElt,false);
1371   for(int i=0;i<nbOfCells;i++)
1372     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1373       if(conn[j]>=0)
1374         retS[conn[j]]=true;
1375   int sz=0;
1376   for(int i=0;i<maxElt;i++)
1377     if(retS[i])
1378       sz++;
1379   DataArrayInt *ret=DataArrayInt::New();
1380   ret->alloc(sz,1);
1381   int *retPtr=ret->getPointer();
1382   for(int i=0;i<maxElt;i++)
1383     if(retS[i])
1384       *retPtr++=i;
1385   return ret;
1386 }
1387
1388 /*!
1389  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1390  * \sa MEDCouplingUMesh::getNodeIdsInUse
1391  */
1392 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1393 {
1394   int nbOfNodes=(int)nodeIdsInUse.size();
1395   int nbOfCells=getNumberOfCells();
1396   const int *connIndex=_nodal_connec_index->getConstPointer();
1397   const int *conn=_nodal_connec->getConstPointer();
1398   for(int i=0;i<nbOfCells;i++)
1399     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1400       if(conn[j]>=0)
1401         {
1402           if(conn[j]<nbOfNodes)
1403             nodeIdsInUse[conn[j]]=true;
1404           else
1405             {
1406               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1407               throw INTERP_KERNEL::Exception(oss.str().c_str());
1408             }
1409         }
1410 }
1411
1412 /*!
1413  * Finds nodes not used in any cell and returns an array giving a new id to every node
1414  * by excluding the unused nodes, for which the array holds -1. The result array is
1415  * a mapping in "Old to New" mode. 
1416  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1417  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1418  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1419  *          if the node is unused or a new id else. The caller is to delete this
1420  *          array using decrRef() as it is no more needed.  
1421  *  \throw If the coordinates array is not set.
1422  *  \throw If the nodal connectivity of cells is not defined.
1423  *  \throw If the nodal connectivity includes an invalid id.
1424  *
1425  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1426  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1427  * \sa computeNodeIdsAlg()
1428  */
1429 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1430 {
1431   nbrOfNodesInUse=-1;
1432   int nbOfNodes=getNumberOfNodes();
1433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1434   ret->alloc(nbOfNodes,1);
1435   int *traducer=ret->getPointer();
1436   std::fill(traducer,traducer+nbOfNodes,-1);
1437   int nbOfCells=getNumberOfCells();
1438   const int *connIndex=_nodal_connec_index->getConstPointer();
1439   const int *conn=_nodal_connec->getConstPointer();
1440   for(int i=0;i<nbOfCells;i++)
1441     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1442       if(conn[j]>=0)
1443         {
1444           if(conn[j]<nbOfNodes)
1445             traducer[conn[j]]=1;
1446           else
1447             {
1448               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1449               throw INTERP_KERNEL::Exception(oss.str().c_str());
1450             }
1451         }
1452   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1453   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1454   return ret.retn();
1455 }
1456
1457 /*!
1458  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1459  * For each cell in \b this the number of nodes constituting cell is computed.
1460  * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1461  * For polyhedrons, the face separation (-1) are excluded from the couting.
1462  * 
1463  * \return a newly allocated array
1464  */
1465 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1466 {
1467   checkConnectivityFullyDefined();
1468   int nbOfCells=getNumberOfCells();
1469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1470   ret->alloc(nbOfCells,1);
1471   int *retPtr=ret->getPointer();
1472   const int *conn=getNodalConnectivity()->getConstPointer();
1473   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1474   for(int i=0;i<nbOfCells;i++,retPtr++)
1475     {
1476       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1477         *retPtr=connI[i+1]-connI[i]-1;
1478       else
1479         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1480     }
1481   return ret.retn();
1482 }
1483
1484 /*!
1485  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1486  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1487  * array mean that the corresponding old node is no more used. 
1488  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1489  *           this->getNumberOfNodes() before call of this method. The caller is to
1490  *           delete this array using decrRef() as it is no more needed. 
1491  *  \throw If the coordinates array is not set.
1492  *  \throw If the nodal connectivity of cells is not defined.
1493  *  \throw If the nodal connectivity includes an invalid id.
1494  *
1495  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1496  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1497  */
1498 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1499 {
1500   int newNbOfNodes=-1;
1501   DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1502   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1503   return traducer;
1504 }
1505
1506 /*!
1507  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1508  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1509  */
1510 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1511 {
1512   switch(compType)
1513     {
1514     case 0:
1515       return AreCellsEqual0(conn,connI,cell1,cell2);
1516     case 1:
1517       return AreCellsEqual1(conn,connI,cell1,cell2);
1518     case 2:
1519       return AreCellsEqual2(conn,connI,cell1,cell2);
1520     case 3:
1521       return AreCellsEqual3(conn,connI,cell1,cell2);
1522     case 7:
1523       return AreCellsEqual7(conn,connI,cell1,cell2);
1524     }
1525   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1526 }
1527
1528 /*!
1529  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1530  */
1531 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1532 {
1533   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1534     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1535   return 0;
1536 }
1537
1538 /*!
1539  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1540  */
1541 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1542 {
1543   int sz=connI[cell1+1]-connI[cell1];
1544   if(sz==connI[cell2+1]-connI[cell2])
1545     {
1546       if(conn[connI[cell1]]==conn[connI[cell2]])
1547         {
1548           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1549           unsigned dim=cm.getDimension();
1550           if(dim!=3)
1551             {
1552               if(dim!=1)
1553                 {
1554                   int sz1=2*(sz-1);
1555                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1556                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1557                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1558                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1559                   return work!=tmp+sz1?1:0;
1560                 }
1561               else
1562                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1563             }
1564           else
1565             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1566         }
1567     }
1568   return 0;
1569 }
1570
1571 /*!
1572  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1573  */
1574 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1575 {
1576   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1577     {
1578       if(conn[connI[cell1]]==conn[connI[cell2]])
1579         {
1580           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1581           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1582           return s1==s2?1:0;
1583         }
1584     }
1585   return 0;
1586 }
1587
1588 /*!
1589  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1590  */
1591 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1592 {
1593   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1594     {
1595       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1596       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1597       return s1==s2?1:0;
1598     }
1599   return 0;
1600 }
1601
1602 /*!
1603  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1604  */
1605 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1606 {
1607   int sz=connI[cell1+1]-connI[cell1];
1608   if(sz==connI[cell2+1]-connI[cell2])
1609     {
1610       if(conn[connI[cell1]]==conn[connI[cell2]])
1611         {
1612           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1613           unsigned dim=cm.getDimension();
1614           if(dim!=3)
1615             {
1616               if(dim!=1)
1617                 {
1618                   int sz1=2*(sz-1);
1619                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1620                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1621                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1622                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1623                   if(work!=tmp+sz1)
1624                     return 1;
1625                   else
1626                     {
1627                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1628                       std::reverse_iterator<int *> it2((int *)tmp);
1629                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1630                         return 2;
1631                       else
1632                         return 0;
1633                     }
1634                   
1635                   return work!=tmp+sz1?1:0;
1636                 }
1637               else
1638                 {//case of SEG2 and SEG3
1639                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1640                     return 1;
1641                   if(!cm.isQuadratic())
1642                     {
1643                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1644                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1645                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1646                         return 2;
1647                       return 0;
1648                     }
1649                   else
1650                     {
1651                       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])
1652                         return 2;
1653                       return 0;
1654                     }
1655                 }
1656             }
1657           else
1658             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1659         }
1660     }
1661   return 0;
1662 }
1663
1664
1665 /*!
1666  * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1667  * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1668  */
1669 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1670 {
1671   if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1672     return false;
1673   std::vector<int> c1,c2;
1674   getNodeIdsOfCell(cellId,c1);
1675   other->getNodeIdsOfCell(cellId,c2);
1676   std::size_t sz=c1.size();
1677   if(sz!=c2.size())
1678     return false;
1679   for(std::size_t i=0;i<sz;i++)
1680     {
1681       std::vector<double> n1,n2;
1682       getCoordinatesOfNode(c1[0],n1);
1683       other->getCoordinatesOfNode(c2[0],n2);
1684       std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1685       std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1686       if(*std::max_element(n1.begin(),n1.end())>prec)
1687         return false;
1688     }
1689   return true;
1690 }
1691
1692 /*!
1693  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1694  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1695  * and result remains unchanged.
1696  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1697  * If in 'candidates' pool -1 value is considered as an empty value.
1698  * WARNING this method returns only ONE set of result !
1699  */
1700 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1701 {
1702   if(candidates.size()<1)
1703     return false;
1704   bool ret=false;
1705   std::vector<int>::const_iterator iter=candidates.begin();
1706   int start=(*iter++);
1707   for(;iter!=candidates.end();iter++)
1708     {
1709       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1710       if(status!=0)
1711         {
1712           if(!ret)
1713             {
1714               result->pushBackSilent(start);
1715               ret=true;
1716             }
1717           if(status==1)
1718             result->pushBackSilent(*iter);
1719           else
1720             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1721         }
1722     }
1723   return ret;
1724 }
1725
1726 /*!
1727  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1728  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1729  *
1730  * \param [in] compType input specifying the technique used to compare cells each other.
1731  *   - 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.
1732  *   - 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)
1733  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1734  *   - 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
1735  * can be used for users not sensitive to orientation of cell
1736  * \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.
1737  * \param [out] commonCells
1738  * \param [out] commonCellsI
1739  * \return the correspondance array old to new in a newly allocated array.
1740  * 
1741  */
1742 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1743 {
1744   checkConnectivityFullyDefined();
1745   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1746   getReverseNodalConnectivity(revNodal,revNodalI);
1747   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1748 }
1749
1750 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1751                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1752 {
1753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1754   int nbOfCells=nodalI->getNumberOfTuples()-1;
1755   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1756   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1757   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1758   std::vector<bool> isFetched(nbOfCells,false);
1759   if(startCellId==0)
1760     {
1761       for(int i=0;i<nbOfCells;i++)
1762         {
1763           if(!isFetched[i])
1764             {
1765               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1766               std::vector<int> v,v2;
1767               if(connOfNode!=connPtr+connIPtr[i+1])
1768                 {
1769                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1770                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1771                   connOfNode++;
1772                 }
1773               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1774                 if(*connOfNode>=0)
1775                   {
1776                     v=v2;
1777                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1778                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1779                     v2.resize(std::distance(v2.begin(),it));
1780                   }
1781               if(v2.size()>1)
1782                 {
1783                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1784                     {
1785                       int pos=commonCellsI->back();
1786                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1787                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1788                         isFetched[*it]=true;
1789                     }
1790                 }
1791             }
1792         }
1793     }
1794   else
1795     {
1796       for(int i=startCellId;i<nbOfCells;i++)
1797         {
1798           if(!isFetched[i])
1799             {
1800               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1801               std::vector<int> v,v2;
1802               if(connOfNode!=connPtr+connIPtr[i+1])
1803                 {
1804                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1805                   connOfNode++;
1806                 }
1807               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1808                 if(*connOfNode>=0)
1809                   {
1810                     v=v2;
1811                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1812                     v2.resize(std::distance(v2.begin(),it));
1813                   }
1814               if(v2.size()>1)
1815                 {
1816                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1817                     {
1818                       int pos=commonCellsI->back();
1819                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1820                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1821                         isFetched[*it]=true;
1822                     }
1823                 }
1824             }
1825         }
1826     }
1827   commonCellsArr=commonCells.retn();
1828   commonCellsIArr=commonCellsI.retn();
1829 }
1830
1831 /*!
1832  * Removes duplicates of cells from \a this mesh and returns an array mapping between
1833  * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1834  * equal cells found.
1835  *  \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1836  *           to write this mesh to the MED file, its cells must be sorted using
1837  *           sortCellsInMEDFileFrmt().
1838  *  \param [in] compType - specifies a cell comparison technique. Meaning of its
1839  *          valid values [0,1,2] is as follows.
1840  *   - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1841  *         connectivity and type. This is the strongest policy.
1842  *   - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1843  *         are based on same nodes and have the same type and orientation.
1844  *   - 2 : "nodal". Two cells are considered equal \c iff they
1845  *         are based on same nodes and have the same type. This is the weakest
1846  *         policy, it can be used by users not sensitive to cell orientation.
1847  *  \param [in] startCellId - specifies the cell id at which search for equal cells
1848  *         starts. By default it is 0, which means that all cells in \a this will be
1849  *         scanned. 
1850  *  \return DataArrayInt - a new instance of DataArrayInt, of length \a
1851  *           this->getNumberOfCells() before call of this method. The caller is to
1852  *           delete this array using decrRef() as it is no more needed. 
1853  *  \throw If the coordinates array is not set.
1854  *  \throw If the nodal connectivity of cells is not defined.
1855  *  \throw If the nodal connectivity includes an invalid id.
1856  *
1857  *  \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1858  *  \ref  py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1859  */
1860 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1861 {
1862   DataArrayInt *commonCells=0,*commonCellsI=0;
1863   findCommonCells(compType,startCellId,commonCells,commonCellsI);
1864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1865   int newNbOfCells=-1;
1866   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1867                                                                                                           commonCellsI->end(),newNbOfCells);
1868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1869   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1870   setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1871   return ret.retn();
1872 }
1873
1874 /*!
1875  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1876  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1877  * than \a other->getNumberOfCells() in the returned array means that there is no
1878  * corresponding cell in \a this mesh.
1879  * It is expected that \a this and \a other meshes share the same node coordinates
1880  * array, if it is not so an exception is thrown. 
1881  *  \param [in] other - the mesh to compare with.
1882  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1883  *         valid values [0,1,2], see zipConnectivityTraducer().
1884  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1885  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1886  *         values. The caller is to delete this array using
1887  *         decrRef() as it is no more needed.
1888  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1889  *         mesh.
1890  *
1891  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1892  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1893  *  \sa checkDeepEquivalOnSameNodesWith()
1894  *  \sa checkGeoEquivalWith()
1895  */
1896 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1897 {
1898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1899   int nbOfCells=getNumberOfCells();
1900   static const int possibleCompType[]={0,1,2};
1901   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1902     {
1903       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1904       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1905       oss << " !";
1906       throw INTERP_KERNEL::Exception(oss.str().c_str());
1907     }
1908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1909   arr=o2n->substr(nbOfCells);
1910   arr->setName(other->getName());
1911   int tmp;
1912   if(other->getNumberOfCells()==0)
1913     return true;
1914   return arr->getMaxValue(tmp)<nbOfCells;
1915 }
1916
1917 /*!
1918  * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1919  * This method tries to determine if \b other is fully included in \b this.
1920  * The main difference is that this method is not expected to throw exception.
1921  * This method has two outputs :
1922  *
1923  * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1924  * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1925  */
1926 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1927 {
1928   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1929   DataArrayInt *commonCells=0,*commonCellsI=0;
1930   int thisNbCells=getNumberOfCells();
1931   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1932   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1933   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1934   int otherNbCells=other->getNumberOfCells();
1935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1936   arr2->alloc(otherNbCells,1);
1937   arr2->fillWithZero();
1938   int *arr2Ptr=arr2->getPointer();
1939   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1940   for(int i=0;i<nbOfCommon;i++)
1941     {
1942       int start=commonCellsPtr[commonCellsIPtr[i]];
1943       if(start<thisNbCells)
1944         {
1945           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1946             {
1947               int sig=commonCellsPtr[j]>0?1:-1;
1948               int val=std::abs(commonCellsPtr[j])-1;
1949               if(val>=thisNbCells)
1950                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1951             }
1952         }
1953     }
1954   arr2->setName(other->getName());
1955   if(arr2->presenceOfValue(0))
1956     return false;
1957   arr=arr2.retn();
1958   return true;
1959 }
1960
1961 /*!
1962  * Merges nodes equal within \a precision and returns an array describing the 
1963  * permutation used to remove duplicate nodes.
1964  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1965  *              considered not coincident.
1966  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1967  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1968  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1969  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1970  *          is to delete this array using decrRef() as it is no more needed.
1971  *  \throw If the coordinates array is not set.
1972  *  \throw If the nodal connectivity of cells is not defined.
1973  *
1974  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1975  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1976  */
1977 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1978 {
1979   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1980   if(areNodesMerged)
1981     renumberNodes(ret->getConstPointer(),newNbOfNodes);
1982   return ret;
1983 }
1984
1985
1986 /*!
1987  * Merges nodes equal within \a precision and returns an array describing the 
1988  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1989  *  of merged nodes is changed to be at their barycenter.
1990  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1991  *              considered not coincident.
1992  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1993  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1994  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1995  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1996  *          is to delete this array using decrRef() as it is no more needed.
1997  *  \throw If the coordinates array is not set.
1998  *  \throw If the nodal connectivity of cells is not defined.
1999  *
2000  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
2001  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
2002  */
2003 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2004 {
2005   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2006   if(areNodesMerged)
2007     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2008   return ret;
2009 }
2010
2011 /*!
2012  * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2013  * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2014  * meshes match with a specified precision, else an exception is thrown and \a this
2015  * remains unchanged. In case of success the nodal connectivity of \a this mesh
2016  * is permuted according to new order of nodes.
2017  * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2018  * coordinates (and so more expensive) than simple equality.
2019  *  \param [in] other - the other mesh whose node coordinates array will be used by
2020  *         \a this mesh in case of their equality.
2021  *  \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2022  *  \throw If the coordinates array of \a this is not set.
2023  *  \throw If the coordinates array of \a other is not set.
2024  *  \throw If the coordinates of \a this and \a other do not match.
2025  */
2026 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2027 {
2028   const DataArrayDouble *coords=other.getCoords();
2029   if(!coords)
2030     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2031   if(!_coords)
2032     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2033   int otherNbOfNodes=other.getNumberOfNodes();
2034   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2035   _coords->incrRef();
2036   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2037   setCoords(newCoords);
2038   bool areNodesMerged;
2039   int newNbOfNodes;
2040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2041   if(!areNodesMerged)
2042     {
2043       setCoords(oldCoords);
2044       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2045     }
2046   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2047   const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2048   if(pt!=da->getConstPointer()+da->getNbOfElems())
2049     {
2050       setCoords(oldCoords);
2051       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2052     }
2053   setCoords(oldCoords);
2054   renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2055   setCoords(coords);
2056 }
2057
2058 /*!
2059  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2060  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2061  * cellIds is not given explicitely but by a range python like.
2062  * 
2063  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2064  * \return a newly allocated
2065  * 
2066  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2067  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2068  */
2069 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2070 {
2071   if(getMeshDimension()!=-1)
2072     {
2073       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2074       if(!keepCoords)
2075         ret->zipCoords();
2076       return ret;
2077     }
2078   else
2079     {
2080       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2081       if(newNbOfCells!=1)
2082         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2083       if(start!=0)
2084         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2085       incrRef();
2086       return const_cast<MEDCouplingUMesh *>(this);
2087     }
2088 }
2089
2090 /*!
2091  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2092  * The result mesh shares or not the node coordinates array with \a this mesh depending
2093  * on \a keepCoords parameter.
2094  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2095  *           to write this mesh to the MED file, its cells must be sorted using
2096  *           sortCellsInMEDFileFrmt().
2097  *  \param [in] begin - an array of cell ids to include to the new mesh.
2098  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2099  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2100  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2101  *         by calling zipCoords().
2102  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2103  *         to delete this mesh using decrRef() as it is no more needed. 
2104  *  \throw If the coordinates array is not set.
2105  *  \throw If the nodal connectivity of cells is not defined.
2106  *  \throw If any cell id in the array \a begin is not valid.
2107  *
2108  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2109  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2110  */
2111 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2112 {
2113   if(getMeshDimension()!=-1)
2114     {
2115       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2116       if(!keepCoords)
2117         ret->zipCoords();
2118       return ret;
2119     }
2120   else
2121     {
2122       if(end-begin!=1)
2123         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2124       if(begin[0]!=0)
2125         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2126       incrRef();
2127       return const_cast<MEDCouplingUMesh *>(this);
2128     }
2129 }
2130
2131 /*!
2132  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2133  *
2134  * 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.
2135  * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2136  * The number of cells of \b this will remain the same with this method.
2137  *
2138  * \param [in] begin begin of cell ids (included) of cells in this to assign
2139  * \param [in] end end of cell ids (excluded) of cells in this to assign
2140  * \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).
2141  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2142  */
2143 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2144 {
2145   checkConnectivityFullyDefined();
2146   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2147   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2148     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2149   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2150     {
2151       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2152       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2153       throw INTERP_KERNEL::Exception(oss.str().c_str());
2154     }
2155   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2156   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2157     {
2158       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2159       throw INTERP_KERNEL::Exception(oss.str().c_str());
2160     }
2161   int nbOfCells=getNumberOfCells();
2162   bool easyAssign=true;
2163   const int *connI=_nodal_connec_index->getConstPointer();
2164   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2165   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2166     {
2167       if(*it>=0 && *it<nbOfCells)
2168         {
2169           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2170         }
2171       else
2172         {
2173           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2174           throw INTERP_KERNEL::Exception(oss.str().c_str());
2175         }
2176     }
2177   if(easyAssign)
2178     {
2179       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2180       computeTypes();
2181     }
2182   else
2183     {
2184       DataArrayInt *arrOut=0,*arrIOut=0;
2185       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2186                                                arrOut,arrIOut);
2187       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2188       setConnectivity(arrOut,arrIOut,true);
2189     }
2190 }
2191
2192 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2193 {
2194   checkConnectivityFullyDefined();
2195   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2196   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2198   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2199     {
2200       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2201       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2202       throw INTERP_KERNEL::Exception(oss.str().c_str());
2203     }
2204   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2205   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2206     {
2207       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2208       throw INTERP_KERNEL::Exception(oss.str().c_str());
2209     }
2210   int nbOfCells=getNumberOfCells();
2211   bool easyAssign=true;
2212   const int *connI=_nodal_connec_index->getConstPointer();
2213   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2214   int it=start;
2215   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2216     {
2217       if(it>=0 && it<nbOfCells)
2218         {
2219           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2220         }
2221       else
2222         {
2223           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2224           throw INTERP_KERNEL::Exception(oss.str().c_str());
2225         }
2226     }
2227   if(easyAssign)
2228     {
2229       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2230       computeTypes();
2231     }
2232   else
2233     {
2234       DataArrayInt *arrOut=0,*arrIOut=0;
2235       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2236                                                 arrOut,arrIOut);
2237       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2238       setConnectivity(arrOut,arrIOut,true);
2239     }
2240 }                      
2241
2242 /*!
2243  * Finds cells whose all nodes are in a given array of node ids.
2244  *  \param [in] partBg - the array of node ids.
2245  *  \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2246  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2247  *          cells. The caller is to delete this array using decrRef() as it is no
2248  *          more needed.
2249  *  \throw If the coordinates array is not set.
2250  *  \throw If the nodal connectivity of cells is not defined.
2251  *  \throw If any cell id in \a partBg is not valid.
2252  *
2253  *  \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2254  *  \ref  py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2255  */
2256 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2257 {
2258   DataArrayInt *cellIdsKept=0;
2259   fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2260   cellIdsKept->setName(getName());
2261   return cellIdsKept;
2262 }
2263
2264 /*!
2265  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2266  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2267  * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2268  * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2269  *
2270  * \param [in] begin input start of array of node ids.
2271  * \param [in] end input end of array of node ids.
2272  * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2273  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2274  */
2275 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2276 {
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2278   checkConnectivityFullyDefined();
2279   int tmp=-1;
2280   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2281   std::vector<bool> fastFinder(sz,false);
2282   for(const int *work=begin;work!=end;work++)
2283     if(*work>=0 && *work<sz)
2284       fastFinder[*work]=true;
2285   int nbOfCells=getNumberOfCells();
2286   const int *conn=getNodalConnectivity()->getConstPointer();
2287   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2288   for(int i=0;i<nbOfCells;i++)
2289     {
2290       int ref=0,nbOfHit=0;
2291       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2292         if(*work2>=0)
2293           {
2294             ref++;
2295             if(fastFinder[*work2])
2296               nbOfHit++;
2297           }
2298       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2299         cellIdsKept->pushBackSilent(i);
2300     }
2301   cellIdsKeptArr=cellIdsKept.retn();
2302 }
2303
2304 /*!
2305  * Finds cells whose all or some nodes are in a given array of node ids.
2306  *  \param [in] begin - the array of node ids.
2307  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2308  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2309  *         array \a begin are returned only, else cells whose any node is in the
2310  *         array \a begin are returned.
2311  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2312  *         cells. The caller is to delete this array using decrRef() as it is no more
2313  *         needed. 
2314  *  \throw If the coordinates array is not set.
2315  *  \throw If the nodal connectivity of cells is not defined.
2316  *  \throw If any cell id in \a begin is not valid.
2317  *
2318  *  \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2319  *  \ref  py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2320  */
2321 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2322 {
2323   DataArrayInt *cellIdsKept=0;
2324   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2325   cellIdsKept->setName(getName());
2326   return cellIdsKept;
2327 }
2328
2329 /*!
2330  Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2331  copy are selected basing on specified node ids and the value of \a fullyIn
2332  parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the 
2333  array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2334  node is in the array of node ids. The created mesh shares the node coordinates array
2335  with \a this mesh.
2336  *  \param [in] begin - the array of node ids.
2337  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2338  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2339  *         array \a begin are copied, else cells whose any node is in the
2340  *         array \a begin are copied.
2341  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2342  *         to delete this mesh using decrRef() as it is no more needed. 
2343  *  \throw If the coordinates array is not set.
2344  *  \throw If the nodal connectivity of cells is not defined.
2345  *  \throw If any node id in \a begin is not valid.
2346  *
2347  *  \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2348  *  \ref  py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2349  */
2350 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2351 {
2352   DataArrayInt *cellIdsKept=0;
2353   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2355   return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2356 }
2357
2358 /*!
2359  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2360  * this->getMeshDimension(), that bound some cells of \a this mesh.
2361  * The cells of lower dimension to include to the result mesh are selected basing on
2362  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2363  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2364  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2365  * created mesh shares the node coordinates array with \a this mesh. 
2366  *  \param [in] begin - the array of node ids.
2367  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2368  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2369  *         array \a begin are added, else cells whose any node is in the
2370  *         array \a begin are added.
2371  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2372  *         to delete this mesh using decrRef() as it is no more needed. 
2373  *  \throw If the coordinates array is not set.
2374  *  \throw If the nodal connectivity of cells is not defined.
2375  *  \throw If any node id in \a begin is not valid.
2376  *
2377  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2378  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2379  */
2380 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2381 {
2382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2383   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2384   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2385   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2386   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2387 }
2388
2389 /*!
2390  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2391  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2392  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2393  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2394  *         by calling zipCoords().
2395  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2396  *         to delete this mesh using decrRef() as it is no more needed. 
2397  *  \throw If the coordinates array is not set.
2398  *  \throw If the nodal connectivity of cells is not defined.
2399  *
2400  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2401  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2402  */
2403 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2404 {
2405   DataArrayInt *desc=DataArrayInt::New();
2406   DataArrayInt *descIndx=DataArrayInt::New();
2407   DataArrayInt *revDesc=DataArrayInt::New();
2408   DataArrayInt *revDescIndx=DataArrayInt::New();
2409   //
2410   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2411   revDesc->decrRef();
2412   desc->decrRef();
2413   descIndx->decrRef();
2414   int nbOfCells=meshDM1->getNumberOfCells();
2415   const int *revDescIndxC=revDescIndx->getConstPointer();
2416   std::vector<int> boundaryCells;
2417   for(int i=0;i<nbOfCells;i++)
2418     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2419       boundaryCells.push_back(i);
2420   revDescIndx->decrRef();
2421   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2422   return ret;
2423 }
2424
2425 /*!
2426  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2427  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2428  * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown. 
2429  */
2430 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2431 {
2432   checkFullyDefined();
2433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2437   //
2438   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2439   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2440   //
2441   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2442   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2443   const int *revDescPtr=revDesc->getConstPointer();
2444   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2445   int nbOfCells=getNumberOfCells();
2446   std::vector<bool> ret1(nbOfCells,false);
2447   int sz=0;
2448   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2449     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2450       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2451   //
2452   DataArrayInt *ret2=DataArrayInt::New();
2453   ret2->alloc(sz,1);
2454   int *ret2Ptr=ret2->getPointer();
2455   sz=0;
2456   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2457     if(*it)
2458       *ret2Ptr++=sz;
2459   ret2->setName("BoundaryCells");
2460   return ret2;
2461 }
2462
2463 /*!
2464  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2465  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2466  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2467  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2468  *
2469  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2470  * This method method returns cells ids set s = s1 + s2 where :
2471  * 
2472  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2473  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2474  *
2475  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2476  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2477  *
2478  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2479  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2480  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2481  */
2482 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2483 {
2484   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2485     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2486   checkConnectivityFullyDefined();
2487   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2488   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2489     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2492   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2493   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2494   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2495   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2496   DataArrayInt *idsOtherInConsti=0;
2497   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2499   if(!b)
2500     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2501   std::set<int> s1;
2502   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2503     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2504   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2505   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2506   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2507   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2509   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2510   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2511   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2512   neighThisPartAuto=0;
2513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2514   const int li[2]={0,1};
2515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2516   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2518   s_renum1->sort();
2519   //
2520   cellIdsRk0=s0arr.retn();
2521   cellIdsRk1=s_renum1.retn();
2522 }
2523
2524 /*!
2525  * 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
2526  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2527  * 
2528  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2529  */
2530 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2531 {
2532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2536   //
2537   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2538   revDesc=0; desc=0; descIndx=0;
2539   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2541   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2542 }
2543
2544 /*!
2545  * Finds nodes lying on the boundary of \a this mesh.
2546  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2547  *          nodes. The caller is to delete this array using decrRef() as it is no
2548  *          more needed.
2549  *  \throw If the coordinates array is not set.
2550  *  \throw If the nodal connectivity of cells is node defined.
2551  *
2552  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2553  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2554  */
2555 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2556 {
2557   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2558   return skin->computeFetchedNodeIds();
2559 }
2560
2561 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2562 {
2563   incrRef();
2564   return const_cast<MEDCouplingUMesh *>(this);
2565 }
2566
2567 /*!
2568  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2569  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2570  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2571  * array is modified accordingly.
2572  *  \param [in] newNodeNumbers - a permutation array, of length \a
2573  *         this->getNumberOfNodes(), in "Old to New" mode. 
2574  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2575  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2576  *  \throw If the coordinates array is not set.
2577  *  \throw If the nodal connectivity of cells is not defined.
2578  *
2579  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2580  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2581  */
2582 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2583 {
2584   MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2585   renumberNodesInConn(newNodeNumbers);
2586 }
2587
2588 /*!
2589  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2590  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2591  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2592  * array is modified accordingly. In contrast to renumberNodes(), location
2593  * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2594  *  \param [in] newNodeNumbers - a permutation array, of length \a
2595  *         this->getNumberOfNodes(), in "Old to New" mode. 
2596  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2597  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2598  *         actually one more than the maximal id in \a newNodeNumbers.
2599  *  \throw If the coordinates array is not set.
2600  *  \throw If the nodal connectivity of cells is not defined.
2601  *
2602  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2603  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2604  */
2605 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2606 {
2607   MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2608   renumberNodesInConn(newNodeNumbers);
2609 }
2610
2611 /*!
2612  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2613  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2614  * 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.
2615  * 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.
2616  * 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.
2617  *
2618  * \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
2619  *             parameter is altered during the call.
2620  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2621  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2622  * \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.
2623  *
2624  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2625  */
2626 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2627                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2628 {
2629   checkFullyDefined();
2630   otherDimM1OnSameCoords.checkFullyDefined();
2631   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2633   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2634     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2635   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2636   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2639   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2640   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2644   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2645   //
2646   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2648   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2649   DataArrayInt *idsTmp=0;
2650   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2652   if(!b)
2653     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2654   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2655   DataArrayInt *tmp0=0,*tmp1=0;
2656   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2661   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2662   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2663   //
2664   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2665   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2666   nodeIdsToDuplicate=s3.retn();
2667 }
2668
2669 /*!
2670  * This method operates a modification of the connectivity and coords in \b this.
2671  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2672  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2673  * 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
2674  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2675  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2676  * 
2677  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2678  * 
2679  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2680  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2681  */
2682 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2683 {
2684   int nbOfNodes=getNumberOfNodes();
2685   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2686   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2687 }
2688
2689 /*!
2690  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2691  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2692  * This method is a generalization of shiftNodeNumbersInConn().
2693  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2694  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2695  *         this->getNumberOfNodes(), in "Old to New" mode. 
2696  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2697  *  \throw If the nodal connectivity of cells is not defined.
2698  *
2699  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2700  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2701  */
2702 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2703 {
2704   checkConnectivityFullyDefined();
2705   int *conn=getNodalConnectivity()->getPointer();
2706   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2707   int nbOfCells=getNumberOfCells();
2708   for(int i=0;i<nbOfCells;i++)
2709     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2710       {
2711         int& node=conn[iconn];
2712         if(node>=0)//avoid polyhedron separator
2713           {
2714             node=newNodeNumbersO2N[node];
2715           }
2716       }
2717   _nodal_connec->declareAsNew();
2718   updateTime();
2719 }
2720
2721 /*!
2722  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2723  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2724  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2725  * 
2726  * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2727  */
2728 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2729 {
2730   checkConnectivityFullyDefined();
2731   int *conn=getNodalConnectivity()->getPointer();
2732   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2733   int nbOfCells=getNumberOfCells();
2734   for(int i=0;i<nbOfCells;i++)
2735     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2736       {
2737         int& node=conn[iconn];
2738         if(node>=0)//avoid polyhedron separator
2739           {
2740             node+=delta;
2741           }
2742       }
2743   _nodal_connec->declareAsNew();
2744   updateTime();
2745 }
2746
2747 /*!
2748  * This method operates a modification of the connectivity in \b this.
2749  * 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.
2750  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2751  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2752  * 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
2753  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2754  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2755  * 
2756  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2757  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2758  * 
2759  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2760  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2761  * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd). 
2762  */
2763 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2764 {
2765   checkConnectivityFullyDefined();
2766   std::map<int,int> m;
2767   int val=offset;
2768   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2769     m[*work]=val;
2770   int *conn=getNodalConnectivity()->getPointer();
2771   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2772   int nbOfCells=getNumberOfCells();
2773   for(int i=0;i<nbOfCells;i++)
2774     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2775       {
2776         int& node=conn[iconn];
2777         if(node>=0)//avoid polyhedron separator
2778           {
2779             std::map<int,int>::iterator it=m.find(node);
2780             if(it!=m.end())
2781               node=(*it).second;
2782           }
2783       }
2784   updateTime();
2785 }
2786
2787 /*!
2788  * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2789  *
2790  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2791  * After the call of this method the number of cells remains the same as before.
2792  *
2793  * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2794  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2795  * be strictly in [0;this->getNumberOfCells()).
2796  *
2797  * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2798  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2799  * should be contained in[0;this->getNumberOfCells()).
2800  * 
2801  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2802  */
2803 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2804 {
2805   checkConnectivityFullyDefined();
2806   int nbCells=getNumberOfCells();
2807   const int *array=old2NewBg;
2808   if(check)
2809     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2810   //
2811   const int *conn=_nodal_connec->getConstPointer();
2812   const int *connI=_nodal_connec_index->getConstPointer();
2813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2814   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2815   newConn->copyStringInfoFrom(*_nodal_connec);
2816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2817   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2818   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2819   //
2820   int *newC=newConn->getPointer();
2821   int *newCI=newConnI->getPointer();
2822   int loc=0;
2823   newCI[0]=loc;
2824   for(int i=0;i<nbCells;i++)
2825     {
2826       std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2827       int nbOfElts=connI[pos+1]-connI[pos];
2828       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2829       loc+=nbOfElts;
2830       newCI[i+1]=loc;
2831     }
2832   //
2833   setConnectivity(newConn,newConnI);
2834   if(check)
2835     delete [] const_cast<int *>(array);
2836 }
2837
2838 /*!
2839  * Finds cells whose bounding boxes intersect a given bounding box.
2840  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2841  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2842  *         zMax (if in 3D). 
2843  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2844  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2845  *         extent of the bounding box of cell to produce an addition to this bounding box.
2846  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2847  *         cells. The caller is to delete this array using decrRef() as it is no more
2848  *         needed. 
2849  *  \throw If the coordinates array is not set.
2850  *  \throw If the nodal connectivity of cells is not defined.
2851  *
2852  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2853  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2854  */
2855 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2856 {
2857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2858   if(getMeshDimension()==-1)
2859     {
2860       elems->pushBackSilent(0);
2861       return elems.retn();
2862     }
2863   int dim=getSpaceDimension();
2864   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2865   const int* conn      = getNodalConnectivity()->getConstPointer();
2866   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2867   const double* coords = getCoords()->getConstPointer();
2868   int nbOfCells=getNumberOfCells();
2869   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2870     {
2871       for (int i=0; i<dim; i++)
2872         {
2873           elem_bb[i*2]=std::numeric_limits<double>::max();
2874           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2875         }
2876
2877       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2878         {
2879           int node= conn[inode];
2880           if(node>=0)//avoid polyhedron separator
2881             {
2882               for (int idim=0; idim<dim; idim++)
2883                 {
2884                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2885                     {
2886                       elem_bb[idim*2] = coords[node*dim+idim] ;
2887                     }
2888                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2889                     {
2890                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2891                     }
2892                 }
2893             }
2894         }
2895       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2896         elems->pushBackSilent(ielem);
2897     }
2898   return elems.retn();
2899 }
2900
2901 /*!
2902  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2903  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2904  * added in 'elems' parameter.
2905  */
2906 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2907 {
2908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2909   if(getMeshDimension()==-1)
2910     {
2911       elems->pushBackSilent(0);
2912       return elems.retn();
2913     }
2914   int dim=getSpaceDimension();
2915   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2916   const int* conn      = getNodalConnectivity()->getConstPointer();
2917   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2918   const double* coords = getCoords()->getConstPointer();
2919   int nbOfCells=getNumberOfCells();
2920   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2921     {
2922       for (int i=0; i<dim; i++)
2923         {
2924           elem_bb[i*2]=std::numeric_limits<double>::max();
2925           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2926         }
2927
2928       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2929         {
2930           int node= conn[inode];
2931           if(node>=0)//avoid polyhedron separator
2932             {
2933               for (int idim=0; idim<dim; idim++)
2934                 {
2935                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2936                     {
2937                       elem_bb[idim*2] = coords[node*dim+idim] ;
2938                     }
2939                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2940                     {
2941                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2942                     }
2943                 }
2944             }
2945         }
2946       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2947         elems->pushBackSilent(ielem);
2948     }
2949   return elems.retn();
2950 }
2951
2952 /*!
2953  * Returns a type of a cell by its id.
2954  *  \param [in] cellId - the id of the cell of interest.
2955  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2956  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2957  */
2958 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2959 {
2960   const int *ptI=_nodal_connec_index->getConstPointer();
2961   const int *pt=_nodal_connec->getConstPointer();
2962   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2963     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2964   else
2965     {
2966       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2967       throw INTERP_KERNEL::Exception(oss.str().c_str());
2968     }
2969 }
2970
2971 /*!
2972  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2973  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2974  * The coordinates array is not considered here.
2975  *
2976  * \param [in] type the geometric type
2977  * \return cell ids in this having geometric type \a type.
2978  */
2979 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2980 {
2981   
2982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2983   ret->alloc(0,1);
2984   checkConnectivityFullyDefined();
2985   int nbCells=getNumberOfCells();
2986   int mdim=getMeshDimension();
2987   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2988   if(mdim!=(int)cm.getDimension())
2989     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2990   const int *ptI=_nodal_connec_index->getConstPointer();
2991   const int *pt=_nodal_connec->getConstPointer();
2992   for(int i=0;i<nbCells;i++)
2993     {
2994       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2995         ret->pushBackSilent(i);
2996     }
2997   return ret.retn();
2998 }
2999
3000 /*!
3001  * Returns nb of cells having the geometric type 'type'.
3002  */
3003 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3004 {
3005   const int *ptI=_nodal_connec_index->getConstPointer();
3006   const int *pt=_nodal_connec->getConstPointer();
3007   int nbOfCells=getNumberOfCells();
3008   int ret=0;
3009   for(int i=0;i<nbOfCells;i++)
3010     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3011       ret++;
3012   return ret;
3013 }
3014
3015 /*!
3016  * Returns the nodal connectivity of a given cell.
3017  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3018  * all returned node ids can be used in getCoordinatesOfNode().
3019  *  \param [in] cellId - an id of the cell of interest.
3020  *  \param [in,out] conn - a vector where the node ids are appended. It is not
3021  *         cleared before the appending.
3022  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3023  */
3024 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3025 {
3026   const int *ptI=_nodal_connec_index->getConstPointer();
3027   const int *pt=_nodal_connec->getConstPointer();
3028   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3029     if(*w>=0)
3030       conn.push_back(*w);
3031 }
3032
3033 std::string MEDCouplingUMesh::simpleRepr() const
3034 {
3035   static const char msg0[]="No coordinates specified !";
3036   std::ostringstream ret;
3037   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3038   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3039   int tmpp1,tmpp2;
3040   double tt=getTime(tmpp1,tmpp2);
3041   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3042   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3043   if(_mesh_dim>=-1)
3044     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3045   else
3046     { ret << " Mesh dimension has not been set or is invalid !"; }
3047   if(_coords!=0)
3048     {
3049       const int spaceDim=getSpaceDimension();
3050       ret << spaceDim << "\nInfo attached on space dimension : ";
3051       for(int i=0;i<spaceDim;i++)
3052         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3053       ret << "\n";
3054     }
3055   else
3056     ret << msg0 << "\n";
3057   ret << "Number of nodes : ";
3058   if(_coords!=0)
3059     ret << getNumberOfNodes() << "\n";
3060   else
3061     ret << msg0 << "\n";
3062   ret << "Number of cells : ";
3063   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3064     ret << getNumberOfCells() << "\n";
3065   else
3066     ret << "No connectivity specified !" << "\n";
3067   ret << "Cell types present : ";
3068   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3069     {
3070       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3071       ret << cm.getRepr() << " ";
3072     }
3073   ret << "\n";
3074   return ret.str();
3075 }
3076
3077 std::string MEDCouplingUMesh::advancedRepr() const
3078 {
3079   std::ostringstream ret;
3080   ret << simpleRepr();
3081   ret << "\nCoordinates array : \n___________________\n\n";
3082   if(_coords)
3083     _coords->reprWithoutNameStream(ret);
3084   else
3085     ret << "No array set !\n";
3086   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3087   reprConnectivityOfThisLL(ret);
3088   return ret.str();
3089 }
3090
3091 /*!
3092  * This method returns a C++ code that is a dump of \a this.
3093  * This method will throw if this is not fully defined.
3094  */
3095 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3096 {
3097   static const char coordsName[]="coords";
3098   static const char connName[]="conn";
3099   static const char connIName[]="connI";
3100   checkFullyDefined();
3101   std::ostringstream ret; ret << "// coordinates" << std::endl;
3102   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3103   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3104   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3105   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3106   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3107   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3108   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3109   return ret.str();
3110 }
3111
3112 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3113 {
3114   std::ostringstream ret;
3115   reprConnectivityOfThisLL(ret);
3116   return ret.str();
3117 }
3118
3119 /*!
3120  * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
3121  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3122  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3123  * some algos).
3124  * 
3125  * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3126  * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
3127  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3128  */
3129 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3130 {
3131   int mdim=getMeshDimension();
3132   if(mdim<0)
3133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3134   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3136   bool needToCpyCT=true;
3137   if(!_nodal_connec)
3138     {
3139       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3140       needToCpyCT=false;
3141     }
3142   else
3143     {
3144       tmp1=_nodal_connec;
3145       tmp1->incrRef();
3146     }
3147   if(!_nodal_connec_index)
3148     {
3149       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3150       needToCpyCT=false;
3151     }
3152   else
3153     {
3154       tmp2=_nodal_connec_index;
3155       tmp2->incrRef();
3156     }
3157   ret->setConnectivity(tmp1,tmp2,false);
3158   if(needToCpyCT)
3159     ret->_types=_types;
3160   if(!_coords)
3161     {
3162       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3163       ret->setCoords(coords);
3164     }
3165   else
3166     ret->setCoords(_coords);
3167   return ret.retn();
3168 }
3169
3170 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3171 {
3172   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3173     {
3174       int nbOfCells=getNumberOfCells();
3175       const int *c=_nodal_connec->getConstPointer();
3176       const int *ci=_nodal_connec_index->getConstPointer();
3177       for(int i=0;i<nbOfCells;i++)
3178         {
3179           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3180           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3181           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3182           stream << "\n";
3183         }
3184     }
3185   else
3186     stream << "Connectivity not defined !\n";
3187 }
3188
3189 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3190 {
3191   const int *ptI=_nodal_connec_index->getConstPointer();
3192   const int *pt=_nodal_connec->getConstPointer();
3193   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3194     return ptI[cellId+1]-ptI[cellId]-1;
3195   else
3196     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3197 }
3198
3199 /*!
3200  * Returns types of cells of the specified part of \a this mesh.
3201  * This method avoids computing sub-mesh explicitely to get its types.
3202  *  \param [in] begin - an array of cell ids of interest.
3203  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3204  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3205  *         describing the cell types. 
3206  *  \throw If the coordinates array is not set.
3207  *  \throw If the nodal connectivity of cells is not defined.
3208  *  \sa getAllTypes()
3209  */
3210 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3211 {
3212   checkFullyDefined();
3213   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3214   const int *conn=_nodal_connec->getConstPointer();
3215   const int *connIndex=_nodal_connec_index->getConstPointer();
3216   for(const int *w=begin;w!=end;w++)
3217     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3218   return ret;
3219 }
3220
3221 /*!
3222  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3223  * a set of types of cells constituting \a this mesh. 
3224  * This method is for advanced users having prepared their connectivity before. For
3225  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3226  *  \param [in] conn - the nodal connectivity array. 
3227  *  \param [in] connIndex - the nodal connectivity index array.
3228  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3229  *         mesh is updated.
3230  */
3231 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3232 {
3233   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3234   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3235   if(isComputingTypes)
3236     computeTypes();
3237   declareAsNew();
3238 }
3239
3240 /*!
3241  * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
3242  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3243  */
3244 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3245                                                                                  _nodal_connec(0),_nodal_connec_index(0),
3246                                                                                 _types(other._types)
3247 {
3248   if(other._nodal_connec)
3249     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3250   if(other._nodal_connec_index)
3251     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3252 }
3253
3254 MEDCouplingUMesh::~MEDCouplingUMesh()
3255 {
3256   if(_nodal_connec)
3257     _nodal_connec->decrRef();
3258   if(_nodal_connec_index)
3259     _nodal_connec_index->decrRef();
3260 }
3261
3262 /*!
3263  * Recomputes a set of cell types of \a this mesh. For more info see
3264  * \ref MEDCouplingUMeshNodalConnectivity.
3265  */
3266 void MEDCouplingUMesh::computeTypes()
3267 {
3268   if(_nodal_connec && _nodal_connec_index)
3269     {
3270       _types.clear();
3271       const int *conn=_nodal_connec->getConstPointer();
3272       const int *connIndex=_nodal_connec_index->getConstPointer();
3273       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3274       if (nbOfElem > 0)
3275         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3276           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3277     }
3278 }
3279
3280 /*!
3281  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3282  */
3283 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3284 {
3285   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3286     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3287 }
3288
3289 /*!
3290  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3291  */
3292 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3293 {
3294   if(!_nodal_connec_index || !_nodal_connec)
3295     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3296 }
3297
3298 /*!
3299  * Returns a number of cells constituting \a this mesh. 
3300  *  \return int - the number of cells in \a this mesh.
3301  *  \throw If the nodal connectivity of cells is not defined.
3302  */
3303 int MEDCouplingUMesh::getNumberOfCells() const
3304
3305   if(_nodal_connec_index)
3306     return _nodal_connec_index->getNumberOfTuples()-1;
3307   else
3308     if(_mesh_dim==-1)
3309       return 1;
3310     else
3311       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3312 }
3313
3314 /*!
3315  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3316  * mesh. For more info see \ref MEDCouplingMeshesPage.
3317  *  \return int - the dimension of \a this mesh.
3318  *  \throw If the mesh dimension is not defined using setMeshDimension().
3319  */
3320 int MEDCouplingUMesh::getMeshDimension() const
3321 {
3322   if(_mesh_dim<-1)
3323     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3324   return _mesh_dim;
3325 }
3326
3327 /*!
3328  * Returns a length of the nodal connectivity array.
3329  * This method is for test reason. Normally the integer returned is not useable by
3330  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3331  *  \return int - the length of the nodal connectivity array.
3332  */
3333 int MEDCouplingUMesh::getMeshLength() const
3334 {
3335   return _nodal_connec->getNbOfElems();
3336 }
3337
3338 /*!
3339  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3340  */
3341 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3342 {
3343   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3344   tinyInfo.push_back(getMeshDimension());
3345   tinyInfo.push_back(getNumberOfCells());
3346   if(_nodal_connec)
3347     tinyInfo.push_back(getMeshLength());
3348   else
3349     tinyInfo.push_back(-1);
3350 }
3351
3352 /*!
3353  * First step of unserialization process.
3354  */
3355 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3356 {
3357   return tinyInfo[6]<=0;
3358 }
3359
3360 /*!
3361  * Second step of serialization process.
3362  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3363  */
3364 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3365 {
3366   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3367   if(tinyInfo[5]!=-1)
3368     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3369 }
3370
3371 /*!
3372  * Third and final step of serialization process.
3373  */
3374 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3375 {
3376   MEDCouplingPointSet::serialize(a1,a2);
3377   if(getMeshDimension()>-1)
3378     {
3379       a1=DataArrayInt::New();
3380       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3381       int *ptA1=a1->getPointer();
3382       const int *conn=getNodalConnectivity()->getConstPointer();
3383       const int *index=getNodalConnectivityIndex()->getConstPointer();
3384       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3385       std::copy(conn,conn+getMeshLength(),ptA1);
3386     }
3387   else
3388     a1=0;
3389 }
3390
3391 /*!
3392  * Second and final unserialization process.
3393  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3394  */
3395 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3396 {
3397   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3398   setMeshDimension(tinyInfo[5]);
3399   if(tinyInfo[7]!=-1)
3400     {
3401       // Connectivity
3402       const int *recvBuffer=a1->getConstPointer();
3403       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3404       myConnecIndex->alloc(tinyInfo[6]+1,1);
3405       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3406       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3407       myConnec->alloc(tinyInfo[7],1);
3408       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3409       setConnectivity(myConnec, myConnecIndex);
3410     }
3411 }
3412
3413 /*!
3414  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3415  * CellIds are given using range specified by a start an end and step.
3416  */
3417 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3418 {
3419   checkFullyDefined();
3420   int ncell=getNumberOfCells();
3421   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3422   ret->_mesh_dim=_mesh_dim;
3423   ret->setCoords(_coords);
3424   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3425   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3426   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3427   int work=start;
3428   const int *conn=_nodal_connec->getConstPointer();
3429   const int *connIndex=_nodal_connec_index->getConstPointer();
3430   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3431     {
3432       if(work>=0 && work<ncell)
3433         {
3434           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3435         }
3436       else
3437         {
3438           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3439           throw INTERP_KERNEL::Exception(oss.str().c_str());
3440         }
3441     }
3442   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3443   int *newConnPtr=newConn->getPointer();
3444   std::set<INTERP_KERNEL::NormalizedCellType> types;
3445   work=start;
3446   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3447     {
3448       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3449       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3450     }
3451   ret->setConnectivity(newConn,newConnI,false);
3452   ret->_types=types;
3453   ret->copyTinyInfoFrom(this);
3454   return ret.retn();
3455 }
3456
3457 /*!
3458  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3459  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3460  * The return newly allocated mesh will share the same coordinates as 'this'.
3461  */
3462 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3463 {
3464   checkFullyDefined();
3465   int ncell=getNumberOfCells();
3466   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3467   ret->_mesh_dim=_mesh_dim;
3468   ret->setCoords(_coords);
3469   std::size_t nbOfElemsRet=std::distance(begin,end);
3470   int *connIndexRet=new int[nbOfElemsRet+1];
3471   connIndexRet[0]=0;
3472   const int *conn=_nodal_connec->getConstPointer();
3473   const int *connIndex=_nodal_connec_index->getConstPointer();
3474   int newNbring=0;
3475   for(const int *work=begin;work!=end;work++,newNbring++)
3476     {
3477       if(*work>=0 && *work<ncell)
3478         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3479       else
3480         {
3481           delete [] connIndexRet;
3482           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3483           throw INTERP_KERNEL::Exception(oss.str().c_str());
3484         }
3485     }
3486   int *connRet=new int[connIndexRet[nbOfElemsRet]];
3487   int *connRetWork=connRet;
3488   std::set<INTERP_KERNEL::NormalizedCellType> types;
3489   for(const int *work=begin;work!=end;work++)
3490     {
3491       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3492       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3493     }
3494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3495   connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3496   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3497   connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3498   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3499   ret->_types=types;
3500   ret->copyTinyInfoFrom(this);
3501   return ret.retn();
3502 }
3503
3504 /*!
3505  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3506  * mesh.<br>
3507  * For 1D cells, the returned field contains lengths.<br>
3508  * For 2D cells, the returned field contains areas.<br>
3509  * For 3D cells, the returned field contains volumes.
3510  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3511  *         orientation, i.e. the volume is always positive.
3512  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3513  *         and one time . The caller is to delete this field using decrRef() as it is no
3514  *         more needed.
3515  */
3516 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3517 {
3518   std::string name="MeasureOfMesh_";
3519   name+=getName();
3520   int nbelem=getNumberOfCells();
3521   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3522   field->setName(name.c_str());
3523   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3524   array->alloc(nbelem,1);
3525   double *area_vol=array->getPointer();
3526   field->setArray(array) ; array=0;
3527   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3528   field->synchronizeTimeWithMesh();
3529   if(getMeshDimension()!=-1)
3530     {
3531       int ipt;
3532       INTERP_KERNEL::NormalizedCellType type;
3533       int dim_space=getSpaceDimension();
3534       const double *coords=getCoords()->getConstPointer();
3535       const int *connec=getNodalConnectivity()->getConstPointer();
3536       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3537       for(int iel=0;iel<nbelem;iel++)
3538         {
3539           ipt=connec_index[iel];
3540           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3541           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);
3542         }
3543       if(isAbs)
3544         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3545     }
3546   else
3547     {
3548       area_vol[0]=std::numeric_limits<double>::max();
3549     }
3550   return field.retn();
3551 }
3552
3553 /*!
3554  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3555  * mesh.<br>
3556  * For 1D cells, the returned array contains lengths.<br>
3557  * For 2D cells, the returned array contains areas.<br>
3558  * For 3D cells, the returned array contains volumes.
3559  * This method avoids building explicitly a part of \a this mesh to perform the work.
3560  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3561  *         orientation, i.e. the volume is always positive.
3562  *  \param [in] begin - an array of cell ids of interest.
3563  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3564  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3565  *          delete this array using decrRef() as it is no more needed.
3566  * 
3567  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3568  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3569  *  \sa getMeasureField()
3570  */
3571 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3572 {
3573   std::string name="PartMeasureOfMesh_";
3574   name+=getName();
3575   int nbelem=(int)std::distance(begin,end);
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3577   array->setName(name.c_str());
3578   array->alloc(nbelem,1);
3579   double *area_vol=array->getPointer();
3580   if(getMeshDimension()!=-1)
3581     {
3582       int ipt;
3583       INTERP_KERNEL::NormalizedCellType type;
3584       int dim_space=getSpaceDimension();
3585       const double *coords=getCoords()->getConstPointer();
3586       const int *connec=getNodalConnectivity()->getConstPointer();
3587       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3588       for(const int *iel=begin;iel!=end;iel++)
3589         {
3590           ipt=connec_index[*iel];
3591           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3592           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3593         }
3594       if(isAbs)
3595         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3596     }
3597   else
3598     {
3599       area_vol[0]=std::numeric_limits<double>::max();
3600     }
3601   return array.retn();
3602 }
3603
3604 /*!
3605  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3606  * \a this one. The returned field contains the dual cell volume for each corresponding
3607  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3608  *  the dual mesh in P1 sens of \a this.<br>
3609  * For 1D cells, the returned field contains lengths.<br>
3610  * For 2D cells, the returned field contains areas.<br>
3611  * For 3D cells, the returned field contains volumes.
3612  * This method is useful to check "P1*" conservative interpolators.
3613  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3614  *         orientation, i.e. the volume is always positive.
3615  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3616  *          nodes and one time. The caller is to delete this array using decrRef() as
3617  *          it is no more needed.
3618  */
3619 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3620 {
3621   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3622   std::string name="MeasureOnNodeOfMesh_";
3623   name+=getName();
3624   int nbNodes=getNumberOfNodes();
3625   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3626   double cst=1./((double)getMeshDimension()+1.);
3627   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3628   array->alloc(nbNodes,1);
3629   double *valsToFill=array->getPointer();
3630   std::fill(valsToFill,valsToFill+nbNodes,0.);
3631   const double *values=tmp->getArray()->getConstPointer();
3632   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3634   getReverseNodalConnectivity(da,daInd);
3635   const int *daPtr=da->getConstPointer();
3636   const int *daIPtr=daInd->getConstPointer();
3637   for(int i=0;i<nbNodes;i++)
3638     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3639       valsToFill[i]+=cst*values[*cell];
3640   ret->setMesh(this);
3641   ret->setArray(array);
3642   return ret.retn();
3643 }
3644
3645 /*!
3646  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3647  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3648  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3649  * and are normalized.
3650  * <br> \a this can be either 
3651  * - a  2D mesh in 2D or 3D space or 
3652  * - an 1D mesh in 2D space.
3653  * 
3654  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3655  *          cells and one time. The caller is to delete this field using decrRef() as
3656  *          it is no more needed.
3657  *  \throw If the nodal connectivity of cells is not defined.
3658  *  \throw If the coordinates array is not set.
3659  *  \throw If the mesh dimension is not set.
3660  *  \throw If the mesh and space dimension is not as specified above.
3661  */
3662 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3663 {
3664   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3665     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3666   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3667   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3668   int nbOfCells=getNumberOfCells();
3669   int nbComp=getMeshDimension()+1;
3670   array->alloc(nbOfCells,nbComp);
3671   double *vals=array->getPointer();
3672   const int *connI=_nodal_connec_index->getConstPointer();
3673   const int *conn=_nodal_connec->getConstPointer();
3674   const double *coords=_coords->getConstPointer();
3675   if(getMeshDimension()==2)
3676     {
3677       if(getSpaceDimension()==3)
3678         {
3679           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3680           const double *locPtr=loc->getConstPointer();
3681           for(int i=0;i<nbOfCells;i++,vals+=3)
3682             {
3683               int offset=connI[i];
3684               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3685               double n=INTERP_KERNEL::norm<3>(vals);
3686               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3687             }
3688         }
3689       else
3690         {
3691           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3692           const double *isAbsPtr=isAbs->getArray()->begin();
3693           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3694             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3695         }
3696     }
3697   else//meshdimension==1
3698     {
3699       double tmp[2];
3700       for(int i=0;i<nbOfCells;i++)
3701         {
3702           int offset=connI[i];
3703           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3704           double n=INTERP_KERNEL::norm<2>(tmp);
3705           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3706           *vals++=-tmp[1];
3707           *vals++=tmp[0];
3708         }
3709     }
3710   ret->setArray(array);
3711   ret->setMesh(this);
3712   ret->synchronizeTimeWithSupport();
3713   return ret.retn();
3714 }
3715
3716 /*!
3717  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3718  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3719  * and are normalized.
3720  * <br> \a this can be either 
3721  * - a  2D mesh in 2D or 3D space or 
3722  * - an 1D mesh in 2D space.
3723  * 
3724  * This method avoids building explicitly a part of \a this mesh to perform the work.
3725  *  \param [in] begin - an array of cell ids of interest.
3726  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3727  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3728  *          cells and one time. The caller is to delete this field using decrRef() as
3729  *          it is no more needed.
3730  *  \throw If the nodal connectivity of cells is not defined.
3731  *  \throw If the coordinates array is not set.
3732  *  \throw If the mesh dimension is not set.
3733  *  \throw If the mesh and space dimension is not as specified above.
3734  *  \sa buildOrthogonalField()
3735  *
3736  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3737  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3738  */
3739 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3740 {
3741   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3742     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3743   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3744   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3745   std::size_t nbelems=std::distance(begin,end);
3746   int nbComp=getMeshDimension()+1;
3747   array->alloc((int)nbelems,nbComp);
3748   double *vals=array->getPointer();
3749   const int *connI=_nodal_connec_index->getConstPointer();
3750   const int *conn=_nodal_connec->getConstPointer();
3751   const double *coords=_coords->getConstPointer();
3752   if(getMeshDimension()==2)
3753     {
3754       if(getSpaceDimension()==3)
3755         {
3756           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3757           const double *locPtr=loc->getConstPointer();
3758           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3759             {
3760               int offset=connI[*i];
3761               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3762               double n=INTERP_KERNEL::norm<3>(vals);
3763               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3764             }
3765         }
3766       else
3767         {
3768           for(std::size_t i=0;i<nbelems;i++)
3769             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3770         }
3771     }
3772   else//meshdimension==1
3773     {
3774       double tmp[2];
3775       for(const int *i=begin;i!=end;i++)
3776         {
3777           int offset=connI[*i];
3778           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3779           double n=INTERP_KERNEL::norm<2>(tmp);
3780           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3781           *vals++=-tmp[1];
3782           *vals++=tmp[0];
3783         }
3784     }
3785   ret->setArray(array);
3786   ret->setMesh(this);
3787   ret->synchronizeTimeWithSupport();
3788   return ret.retn();
3789 }
3790
3791 /*!
3792  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3793  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3794  * and are \b not normalized.
3795  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3796  *          cells and one time. The caller is to delete this field using decrRef() as
3797  *          it is no more needed.
3798  *  \throw If the nodal connectivity of cells is not defined.
3799  *  \throw If the coordinates array is not set.
3800  *  \throw If \a this->getMeshDimension() != 1.
3801  *  \throw If \a this mesh includes cells of type other than SEG2.
3802  */
3803 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3804 {
3805    if(getMeshDimension()!=1)
3806     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3807    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3808      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3809    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3810    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3811    int nbOfCells=getNumberOfCells();
3812    int spaceDim=getSpaceDimension();
3813    array->alloc(nbOfCells,spaceDim);
3814    double *pt=array->getPointer();
3815    const double *coo=getCoords()->getConstPointer();
3816    std::vector<int> conn;
3817    conn.reserve(2);
3818    for(int i=0;i<nbOfCells;i++)
3819      {
3820        conn.resize(0);
3821        getNodeIdsOfCell(i,conn);
3822        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3823      }
3824    ret->setArray(array);
3825    ret->setMesh(this);
3826    ret->synchronizeTimeWithSupport();
3827    return ret.retn();   
3828 }
3829
3830 /*!
3831  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3832  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3833  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3834  * from. If a result face is shared by two 3D cells, then the face in included twice in
3835  * the result mesh.
3836  *  \param [in] origin - 3 components of a point defining location of the plane.
3837  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3838  *         must be greater than 1e-6.
3839  *  \param [in] eps - half-thickness of the plane.
3840  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3841  *         producing correspondent 2D cells. The caller is to delete this array
3842  *         using decrRef() as it is no more needed.
3843  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3844  *         not share the node coordinates array with \a this mesh. The caller is to
3845  *         delete this mesh using decrRef() as it is no more needed.  
3846  *  \throw If the coordinates array is not set.
3847  *  \throw If the nodal connectivity of cells is not defined.
3848  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3849  *  \throw If magnitude of \a vec is less than 1e-6.
3850  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3851  *  \throw If \a this includes quadratic cells.
3852  */
3853 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3854 {
3855   checkFullyDefined();
3856   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3858   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3859   if(candidates->empty())
3860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3861   std::vector<int> nodes;
3862   DataArrayInt *cellIds1D=0;
3863   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3864   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3866   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3869   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3870   revDesc2=0; revDescIndx2=0;
3871   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3872   revDesc1=0; revDescIndx1=0;
3873   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3875   //
3876   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3877   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3878     cut3DCurve[*it]=-1;
3879   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3880   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3881   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3882                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3883                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3885   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3886   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3887   if(cellIds2->empty())
3888     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3889   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3890   ret->setCoords(mDesc1->getCoords());
3891   ret->setConnectivity(conn,connI,true);
3892   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3893   return ret.retn();
3894 }
3895
3896 /*!
3897  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3898 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
3899 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3900 the result mesh.
3901  *  \param [in] origin - 3 components of a point defining location of the plane.
3902  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3903  *         must be greater than 1e-6.
3904  *  \param [in] eps - half-thickness of the plane.
3905  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3906  *         producing correspondent segments. The caller is to delete this array
3907  *         using decrRef() as it is no more needed.
3908  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3909  *         mesh in 3D space. This mesh does not share the node coordinates array with
3910  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3911  *         no more needed. 
3912  *  \throw If the coordinates array is not set.
3913  *  \throw If the nodal connectivity of cells is not defined.
3914  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3915  *  \throw If magnitude of \a vec is less than 1e-6.
3916  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3917  *  \throw If \a this includes quadratic cells.
3918  */
3919 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3920 {
3921   checkFullyDefined();
3922   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3925   if(candidates->empty())
3926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3927   std::vector<int> nodes;
3928   DataArrayInt *cellIds1D=0;
3929   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3930   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3931   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3932   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3933   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3934   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3935   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3936   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3938   //
3939   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3940   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3941     cut3DCurve[*it]=-1;
3942   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3943   int ncellsSub=subMesh->getNumberOfCells();
3944   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3945   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3946                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3947                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3949   conn->alloc(0,1);
3950   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3951   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3952   for(int i=0;i<ncellsSub;i++)
3953     {
3954       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3955         {
3956           if(cut3DSurf[i].first!=-2)
3957             {
3958               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3959               connI->pushBackSilent(conn->getNumberOfTuples());
3960               cellIds2->pushBackSilent(i);
3961             }
3962           else
3963             {
3964               int cellId3DSurf=cut3DSurf[i].second;
3965               int offset=nodalI[cellId3DSurf]+1;
3966               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3967               for(int j=0;j<nbOfEdges;j++)
3968                 {
3969                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3970                   connI->pushBackSilent(conn->getNumberOfTuples());
3971                   cellIds2->pushBackSilent(cellId3DSurf);
3972                 }
3973             }
3974         }
3975     }
3976   if(cellIds2->empty())
3977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3978   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3979   ret->setCoords(mDesc1->getCoords());
3980   ret->setConnectivity(conn,connI,true);
3981   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3982   return ret.retn();
3983 }
3984
3985 /*!
3986  * Finds cells whose bounding boxes intersect a given plane.
3987  *  \param [in] origin - 3 components of a point defining location of the plane.
3988  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3989  *         must be greater than 1e-6.
3990  *  \param [in] eps - half-thickness of the plane.
3991  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3992  *         cells. The caller is to delete this array using decrRef() as it is no more
3993  *         needed.
3994  *  \throw If the coordinates array is not set.
3995  *  \throw If the nodal connectivity of cells is not defined.
3996  *  \throw If \a this->getSpaceDimension() != 3.
3997  *  \throw If magnitude of \a vec is less than 1e-6.
3998  *  \sa buildSlice3D()
3999  */
4000 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
4001 {
4002   checkFullyDefined();
4003   if(getSpaceDimension()!=3)
4004     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4005   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4006   if(normm<1e-6)
4007     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4008   double vec2[3];
4009   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4010   double angle=acos(vec[2]/normm);
4011   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4012   double bbox[6];
4013   if(angle>eps)
4014     {
4015       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4016       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4017       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4018       mw->setCoords(coo);
4019       mw->getBoundingBox(bbox);
4020       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4021       cellIds=mw->getCellsInBoundingBox(bbox,eps);
4022     }
4023   else
4024     {
4025       getBoundingBox(bbox);
4026       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4027       cellIds=getCellsInBoundingBox(bbox,eps);
4028     }
4029   return cellIds.retn();
4030 }
4031
4032 /*!
4033  * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4034  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4035  * No consideration of coordinate is done by this method.
4036  * 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)
4037  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4038  */
4039 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4040 {
4041   if(getMeshDimension()!=1)
4042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4043   int nbCells=getNumberOfCells();
4044   if(nbCells<1)
4045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4046   const int *connI=_nodal_connec_index->getConstPointer();
4047   const int *conn=_nodal_connec->getConstPointer();
4048   int ref=conn[connI[0]+2];
4049   for(int i=1;i<nbCells;i++)
4050     {
4051       if(conn[connI[i]+1]!=ref)
4052         return false;
4053       ref=conn[connI[i]+2];
4054     }
4055   return true;
4056 }
4057
4058 /*!
4059  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4060  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4061  * @param pt reference point of the line
4062  * @param v normalized director vector of the line
4063  * @param eps max precision before throwing an exception
4064  * @param res output of size this->getNumberOfCells
4065  */
4066 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4067 {
4068   if(getMeshDimension()!=1)
4069     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4070    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4071      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4072    if(getSpaceDimension()!=3)
4073      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4074    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4075    const double *fPtr=f->getArray()->getConstPointer();
4076    double tmp[3];
4077    for(int i=0;i<getNumberOfCells();i++)
4078      {
4079        const double *tmp1=fPtr+3*i;
4080        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4081        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4082        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4083        double n1=INTERP_KERNEL::norm<3>(tmp);
4084        n1/=INTERP_KERNEL::norm<3>(tmp1);
4085        if(n1>eps)
4086          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4087      }
4088    const double *coo=getCoords()->getConstPointer();
4089    for(int i=0;i<getNumberOfNodes();i++)
4090      {
4091        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4092        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4093        res[i]=std::accumulate(tmp,tmp+3,0.);
4094      }
4095 }
4096
4097 /*!
4098  * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance. 
4099  * \a this is expected to be a mesh so that its space dimension is equal to its
4100  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4101  * 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).
4102  * 
4103  * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found 
4104  * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked
4105  * to the node that minimizes distance with the input point then -1 is returned in cellId.
4106  *
4107  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4108  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4109  *
4110  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4111  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4112  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4113  * \return the positive value of the distance.
4114  * \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
4115  * dimension - 1.
4116  * \sa DataArrayDouble::distanceToTuple
4117  */
4118 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
4119 {
4120   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4121   if(meshDim!=spaceDim-1)
4122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4123   if(meshDim!=2 && meshDim!=1)
4124     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4125   checkFullyDefined();
4126   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4127     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4128   nodeId=-1;
4129   double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
4130   if(nodeId==-1)
4131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
4132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
4133   switch(meshDim)
4134     {
4135     case 2:
4136       {
4137         distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
4138         return ret0;
4139       }
4140     case 1:
4141       {
4142         distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
4143         return ret0;
4144       }
4145     default:
4146       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4147     }
4148   
4149   return ret0;
4150 }
4151
4152
4153 /*!
4154  * \param [in] pt the start pointer (included) of the coordinates of the point
4155  * \param [in] cellIds
4156  * \param [in,out] ret0 the min distance between \a this and the external input point
4157  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4158  * \sa MEDCouplingUMesh::distanceToPoint
4159  */
4160 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4161 {
4162   const double *coords=_coords->getConstPointer();
4163   cellId=-1; 
4164   if(cellIds->empty())
4165     return;
4166   const int *ptr=_nodal_connec->getConstPointer();
4167   const int *ptrI=_nodal_connec_index->getConstPointer();
4168   for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4169     {
4170       switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4171         {
4172         case INTERP_KERNEL::NORM_TRI3:
4173           {
4174             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
4175             if(tmp<ret0)
4176               { ret0=tmp; cellId=*zeCell; }
4177             break;
4178           }
4179         case INTERP_KERNEL::NORM_QUAD4:
4180         case INTERP_KERNEL::NORM_POLYGON:
4181           {
4182             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
4183             if(tmp<ret0)
4184               { ret0=tmp; cellId=*zeCell; }
4185             break;
4186           }
4187         default:
4188           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4189         }
4190     }
4191 }
4192
4193 /*!
4194  * \param [in] pt the start pointer (included) of the coordinates of the point
4195  * \param [in] cellIds
4196  * \param [in,out] ret0 the min distance between \a this and the external input point
4197  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4198  * \sa MEDCouplingUMesh::distanceToPoint
4199  */
4200 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4201 {
4202   const double *coords=_coords->getConstPointer();
4203   if(cellIds->empty())
4204     { cellId=-1; return; }
4205   const int *ptr=_nodal_connec->getConstPointer();
4206   const int *ptrI=_nodal_connec_index->getConstPointer();
4207   for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4208     {
4209        switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4210         {
4211         case INTERP_KERNEL::NORM_SEG2:
4212           {
4213             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
4214             if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
4215             if(tmp<ret0)
4216               { ret0=tmp; cellId=*zeCell; }
4217             break;
4218           }
4219         default:
4220           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4221         }
4222     }
4223 }
4224
4225 /*!
4226  * Finds cells in contact with a ball (i.e. a point with precision). 
4227  * \warning This method is suitable if the caller intends to evaluate only one
4228  *          point, for more points getCellsContainingPoints() is recommended as it is
4229  *          faster. 
4230  *  \param [in] pos - array of coordinates of the ball central point.
4231  *  \param [in] eps - ball radius.
4232  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4233  *         if there are no such cells.
4234  *  \throw If the coordinates array is not set.
4235  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4236  */
4237 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4238 {
4239   std::vector<int> elts;
4240   getCellsContainingPoint(pos,eps,elts);
4241   if(elts.empty())
4242     return -1;
4243   return elts.front();
4244 }
4245
4246 /*!
4247  * Finds cells in contact with a ball (i.e. a point with precision).
4248  * \warning This method is suitable if the caller intends to evaluate only one
4249  *          point, for more points getCellsContainingPoints() is recommended as it is
4250  *          faster. 
4251  *  \param [in] pos - array of coordinates of the ball central point.
4252  *  \param [in] eps - ball radius.
4253  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4254  *         before inserting ids.
4255  *  \throw If the coordinates array is not set.
4256  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4257  *
4258  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4259  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4260  */
4261 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4262 {
4263   std::vector<int> eltsIndex;
4264   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4265 }
4266
4267 /// @cond INTERNAL
4268
4269 namespace ParaMEDMEM
4270 {
4271   template<const int SPACEDIMM>
4272   class DummyClsMCUG
4273   {
4274   public:
4275     static const int MY_SPACEDIM=SPACEDIMM;
4276     static const int MY_MESHDIM=8;
4277     typedef int MyConnType;
4278     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4279     // begin
4280     // useless, but for windows compilation ...
4281     const double* getCoordinatesPtr() const { return 0; }
4282     const int* getConnectivityPtr() const { return 0; }
4283     const int* getConnectivityIndexPtr() const { return 0; }
4284     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4285     // end
4286   };
4287
4288   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4289   {
4290     INTERP_KERNEL::Edge *ret=0;
4291     switch(typ)
4292       {
4293       case INTERP_KERNEL::NORM_SEG2:
4294         {
4295           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4296           break;
4297         }
4298       case INTERP_KERNEL::NORM_SEG3:
4299         {
4300           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4301           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4302           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4303           bool colinearity=inters.areColinears();
4304           delete e1; delete e2;
4305           if(colinearity)
4306             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4307           else
4308             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4309           mapp2[bg[2]].second=false;
4310           break;
4311         }
4312       default:
4313         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4314       }
4315     return ret;
4316   }
4317
4318   /*!
4319    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4320    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4321    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4322    */
4323   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4324   {
4325     mapp.clear();
4326     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4327     const double *coo=mDesc->getCoords()->getConstPointer();
4328     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4329     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4330     std::set<int> s;
4331     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4332       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4333     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4334       {
4335         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4336         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4337       }
4338     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4339     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4340       {
4341         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4342         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4343       }
4344     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4345       {
4346         if((*it2).second.second)
4347           mapp[(*it2).second.first]=(*it2).first;
4348         ((*it2).second.first)->decrRef();
4349       }
4350     return ret;
4351   }
4352
4353   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4354   {
4355     if(nodeId>=offset2)
4356       {
4357         int locId=nodeId-offset2;
4358         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4359       }
4360     if(nodeId>=offset1)
4361       {
4362         int locId=nodeId-offset1;
4363         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4364       }
4365     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4366   }
4367
4368   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4369                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4370                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4371   {
4372     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4373       {
4374         int eltId1=abs(*desc1)-1;
4375         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4376           {
4377             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4378             if(it==mappRev.end())
4379               {
4380                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4381                 mapp[node]=*it1;
4382                 mappRev[*it1]=node;
4383               }
4384           }
4385       }
4386   }
4387 }
4388
4389 /// @endcond
4390
4391 template<int SPACEDIM>
4392 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4393                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4394 {
4395   std::vector<double> bbox;
4396   eltsIndex.resize(nbOfPoints+1);
4397   eltsIndex[0]=0;
4398   elts.clear();
4399   getBoundingBoxForBBTree(bbox);
4400   int nbOfCells=getNumberOfCells();
4401   const int *conn=_nodal_connec->getConstPointer();
4402   const int *connI=_nodal_connec_index->getConstPointer();
4403   double bb[2*SPACEDIM];
4404   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4405   for(int i=0;i<nbOfPoints;i++)
4406     {
4407       eltsIndex[i+1]=eltsIndex[i];
4408       for(int j=0;j<SPACEDIM;j++)
4409         {
4410           bb[2*j]=pos[SPACEDIM*i+j];
4411           bb[2*j+1]=pos[SPACEDIM*i+j];
4412         }
4413       std::vector<int> candidates;
4414       myTree.getIntersectingElems(bb,candidates);
4415       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4416         {
4417           int sz=connI[(*iter)+1]-connI[*iter]-1;
4418           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4419                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4420                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4421             {
4422               eltsIndex[i+1]++;
4423               elts.push_back(*iter);
4424             }
4425         }
4426     }
4427 }
4428 /*!
4429  * Finds cells in contact with several balls (i.e. points with precision).
4430  * This method is an extension of getCellContainingPoint() and
4431  * getCellsContainingPoint() for the case of multiple points.
4432  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4433  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4434  *         this->getSpaceDimension() * \a nbOfPoints 
4435  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4436  *  \param [in] eps - radius of balls (i.e. the precision).
4437  *  \param [in,out] elts - vector returning ids of found cells.
4438  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4439  *         dividing cell ids in \a elts into groups each referring to one
4440  *         point. Its every element (except the last one) is an index pointing to the
4441  *         first id of a group of cells. For example cells in contact with the *i*-th
4442  *         point are described by following range of indices:
4443  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4444  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4445  *         Number of cells in contact with the *i*-th point is
4446  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4447  *  \throw If the coordinates array is not set.
4448  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4449  *
4450  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4451  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4452  */
4453 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4454                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4455 {
4456   int spaceDim=getSpaceDimension();
4457   int mDim=getMeshDimension();
4458   if(spaceDim==3)
4459     {
4460       if(mDim==3)
4461         {
4462           const double *coords=_coords->getConstPointer();
4463           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4464         }
4465       /*else if(mDim==2)
4466         {
4467           
4468         }*/
4469       else
4470         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4471     }
4472   else if(spaceDim==2)
4473     {
4474       if(mDim==2)
4475         {
4476           const double *coords=_coords->getConstPointer();
4477           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4478         }
4479       else
4480         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4481     }
4482   else if(spaceDim==1)
4483     {
4484       if(mDim==1)
4485         {
4486           const double *coords=_coords->getConstPointer();
4487           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4488         }
4489       else
4490         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4491     }
4492   else
4493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4494 }
4495
4496 /*!
4497  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4498  * least two its edges intersect each other anywhere except their extremities. An
4499  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4500  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4501  *         cleared before filling in.
4502  *  \param [in] eps - precision.
4503  *  \throw If \a this->getMeshDimension() != 2.
4504  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4505  */
4506 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4507 {
4508   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4509   if(getMeshDimension()!=2)
4510     throw INTERP_KERNEL::Exception(msg);
4511   int spaceDim=getSpaceDimension();
4512   if(spaceDim!=2 && spaceDim!=3)
4513     throw INTERP_KERNEL::Exception(msg);
4514   const int *conn=_nodal_connec->getConstPointer();
4515   const int *connI=_nodal_connec_index->getConstPointer();
4516   int nbOfCells=getNumberOfCells();
4517   std::vector<double> cell2DinS2;
4518   for(int i=0;i<nbOfCells;i++)
4519     {
4520       int offset=connI[i];
4521       int nbOfNodesForCell=connI[i+1]-offset-1;
4522       if(nbOfNodesForCell<=3)
4523         continue;
4524       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4525       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4526       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4527         cells.push_back(i);
4528       cell2DinS2.clear();
4529     }
4530 }
4531
4532 /*!
4533  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4534  *
4535  * 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.
4536  * 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.
4537  * 
4538  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4539  * This convex envelop is computed using Jarvis march algorithm.
4540  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4541  * 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)
4542  * 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.
4543  *
4544  * @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.
4545  */
4546 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4547 {
4548   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4549     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4550   checkFullyDefined();
4551   const double *coords=getCoords()->getConstPointer();
4552   int nbOfCells=getNumberOfCells();
4553   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4554   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4555   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4556   int *workIndexOut=nodalConnecIndexOut->getPointer();
4557   *workIndexOut=0;
4558   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4559   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4560   std::set<INTERP_KERNEL::NormalizedCellType> types;
4561   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4562   isChanged->alloc(0,1);
4563   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4564     {
4565       int pos=nodalConnecOut->getNumberOfTuples();
4566       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4567         isChanged->pushBackSilent(i);
4568       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4569       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4570     }
4571   if(isChanged->empty())
4572     return 0;
4573   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4574   _types=types;
4575   return isChanged.retn();
4576 }
4577
4578 /*!
4579  * This method is \b NOT const because it can modify 'this'.
4580  * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4581  * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4582  * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4583  * \b 1 for translation and rotation around point of 'mesh1D'.
4584  * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.  
4585  */
4586 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4587 {
4588   checkFullyDefined();
4589   mesh1D->checkFullyDefined();
4590   if(!mesh1D->isContiguous1D())
4591     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4592   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4593     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4594   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4595     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4596   if(mesh1D->getMeshDimension()!=1)
4597     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4598   bool isQuad=false;
4599   if(isPresenceOfQuadratic())
4600     {
4601       if(mesh1D->isFullyQuadratic())
4602         isQuad=true;
4603       else
4604         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4605     }
4606   zipCoords();
4607   int oldNbOfNodes=getNumberOfNodes();
4608   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4609   switch(policy)
4610     {
4611     case 0:
4612       {
4613         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4614         break;
4615       }
4616     case 1:
4617       {
4618         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4619         break;
4620       }
4621     default:
4622       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4623     }
4624   setCoords(newCoords);
4625   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4626   updateTime();
4627   return ret.retn();
4628 }
4629
4630 /*!
4631  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4632  * If it is not the case an exception will be thrown.
4633  * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4634  * intersection of plane defined by ('origin','vec').
4635  * This method has one in/out parameter : 'cut3DCurve'.
4636  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4637  * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4638  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4639  * This method will throw an exception if 'this' contains a non linear segment.
4640  */
4641 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4642 {
4643   checkFullyDefined();
4644   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4645     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4646   int ncells=getNumberOfCells();
4647   int nnodes=getNumberOfNodes();
4648   double vec2[3],vec3[3],vec4[3];
4649   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4650   if(normm<1e-6)
4651     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4652   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4653   const int *conn=_nodal_connec->getConstPointer();
4654   const int *connI=_nodal_connec_index->getConstPointer();
4655   const double *coo=_coords->getConstPointer();
4656   std::vector<double> addCoo;
4657   for(int i=0;i<ncells;i++)
4658     {
4659       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4660         {
4661           if(cut3DCurve[i]==-2)
4662             {
4663               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4664               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4665               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4666               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4667               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4668                 {
4669                   const double *st2=coo+3*st;
4670                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4671                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4672                   if(pos>eps && pos<1-eps)
4673                     {
4674                       int nNode=((int)addCoo.size())/3;
4675                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4676                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4677                       cut3DCurve[i]=nnodes+nNode;
4678                     }
4679                 }
4680             }
4681         }
4682       else
4683         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4684     }
4685   if(!addCoo.empty())
4686     {
4687       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4688       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4689       coo2->alloc(newNbOfNodes,3);
4690       double *tmp=coo2->getPointer();
4691       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4692       std::copy(addCoo.begin(),addCoo.end(),tmp);
4693       DataArrayDouble::SetArrayIn(coo2,_coords);
4694     }
4695 }
4696
4697 /*!
4698  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4699  * @param mesh1D is the input 1D mesh used for translation computation.
4700  * @return newCoords new coords filled by this method. 
4701  */
4702 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4703 {
4704   int oldNbOfNodes=getNumberOfNodes();
4705   int nbOf1DCells=mesh1D->getNumberOfCells();
4706   int spaceDim=getSpaceDimension();
4707   DataArrayDouble *ret=DataArrayDouble::New();
4708   std::vector<bool> isQuads;
4709   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4710   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4711   double *retPtr=ret->getPointer();
4712   const double *coords=getCoords()->getConstPointer();
4713   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4714   std::vector<int> v;
4715   std::vector<double> c;
4716   double vec[3];
4717   v.reserve(3);
4718   c.reserve(6);
4719   for(int i=0;i<nbOf1DCells;i++)
4720     {
4721       v.resize(0);
4722       mesh1D->getNodeIdsOfCell(i,v);
4723       c.resize(0);
4724       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4725       mesh1D->getCoordinatesOfNode(v[0],c);
4726       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4727       for(int j=0;j<oldNbOfNodes;j++)
4728         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4729       if(isQuad)
4730         {
4731           c.resize(0);
4732           mesh1D->getCoordinatesOfNode(v[1],c);
4733           mesh1D->getCoordinatesOfNode(v[0],c);
4734           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4735           for(int j=0;j<oldNbOfNodes;j++)
4736             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4737         }
4738     }
4739   ret->copyStringInfoFrom(*getCoords());
4740   return ret;
4741 }
4742
4743 /*!
4744  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4745  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4746  * @return newCoords new coords filled by this method. 
4747  */
4748 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4749 {
4750   if(mesh1D->getSpaceDimension()==2)
4751     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4752   if(mesh1D->getSpaceDimension()==3)
4753     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4754   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4755 }
4756
4757 /*!
4758  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4759  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4760  * @return newCoords new coords filled by this method. 
4761  */
4762 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4763 {
4764   if(isQuad)
4765     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4766   int oldNbOfNodes=getNumberOfNodes();
4767   int nbOf1DCells=mesh1D->getNumberOfCells();
4768   if(nbOf1DCells<2)
4769     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4770   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4771   int nbOfLevsInVec=nbOf1DCells+1;
4772   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4773   double *retPtr=ret->getPointer();
4774   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4775   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4776   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4777   tmp->setCoords(tmp2);
4778   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4779   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4780   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4781   for(int i=1;i<nbOfLevsInVec;i++)
4782     {
4783       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4784       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4785       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4786       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4787       tmp->translate(vec);
4788       double tmp3[2],radius,alpha,alpha0;
4789       const double *p0=i+1<nbOfLevsInVec?begin:third;
4790       const double *p1=i+1<nbOfLevsInVec?end:begin;
4791       const double *p2=i+1<nbOfLevsInVec?third:end;
4792       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4793       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4794       double angle=acos(cosangle/(radius*radius));
4795       tmp->rotate(end,0,angle);
4796       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4797     }
4798   return ret.retn();
4799 }
4800
4801 /*!
4802  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4803  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4804  * @return newCoords new coords filled by this method. 
4805  */
4806 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4807 {
4808   if(isQuad)
4809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4810   int oldNbOfNodes=getNumberOfNodes();
4811   int nbOf1DCells=mesh1D->getNumberOfCells();
4812   if(nbOf1DCells<2)
4813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4814   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4815   int nbOfLevsInVec=nbOf1DCells+1;
4816   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4817   double *retPtr=ret->getPointer();
4818   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4819   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4820   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4821   tmp->setCoords(tmp2);
4822   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4823   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4824   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4825   for(int i=1;i<nbOfLevsInVec;i++)
4826     {
4827       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4828       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4829       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4830       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4831       tmp->translate(vec);
4832       double tmp3[2],radius,alpha,alpha0;
4833       const double *p0=i+1<nbOfLevsInVec?begin:third;
4834       const double *p1=i+1<nbOfLevsInVec?end:begin;
4835       const double *p2=i+1<nbOfLevsInVec?third:end;
4836       double vecPlane[3]={
4837         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4838         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4839         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4840       };
4841       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4842       if(norm>1.e-7)
4843         {
4844           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4845           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4846           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4847           double s2=norm2;
4848           double c2=cos(asin(s2));
4849           double m[3][3]={
4850             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4851             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4852             {-vec2[1]*s2, vec2[0]*s2, c2}
4853           };
4854           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4855           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4856           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4857           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4858           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4859           double angle=acos(cosangle/(radius*radius));
4860           tmp->rotate(end,vecPlane,angle);
4861           
4862         }
4863       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4864     }
4865   return ret.retn();
4866 }
4867
4868 /*!
4869  * This method is private because not easy to use for end user. This method is const contrary to
4870  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4871  * the coords sorted slice by slice.
4872  * @param isQuad specifies presence of quadratic cells.
4873  */
4874 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4875 {
4876   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4877   int nbOf2DCells=getNumberOfCells();
4878   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4879   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4880   const int *conn=_nodal_connec->getConstPointer();
4881   const int *connI=_nodal_connec_index->getConstPointer();
4882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4884   newConnI->alloc(nbOf3DCells+1,1);
4885   int *newConnIPtr=newConnI->getPointer();
4886   *newConnIPtr++=0;
4887   std::vector<int> newc;
4888   for(int j=0;j<nbOf2DCells;j++)
4889     {
4890       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4891       *newConnIPtr++=(int)newc.size();
4892     }
4893   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4894   int *newConnPtr=newConn->getPointer();
4895   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4896   newConnIPtr=newConnI->getPointer();
4897   for(int iz=0;iz<nbOf1DCells;iz++)
4898     {
4899       if(iz!=0)
4900         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4901       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4902         {
4903           int icell=(int)(iter-newc.begin());
4904           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4905             {
4906               if(*iter!=-1)
4907                 *newConnPtr=(*iter)+iz*deltaPerLev;
4908               else
4909                 *newConnPtr=-1;
4910             }
4911           else
4912             *newConnPtr=(*iter);
4913         }
4914     }
4915   ret->setConnectivity(newConn,newConnI,true);
4916   ret->setCoords(getCoords());
4917   return ret;
4918 }
4919
4920 /*!
4921  * Checks if \a this mesh is constituted by only quadratic cells.
4922  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4923  *  \throw If the coordinates array is not set.
4924  *  \throw If the nodal connectivity of cells is not defined.
4925  */
4926 bool MEDCouplingUMesh::isFullyQuadratic() const
4927 {
4928   checkFullyDefined();
4929   bool ret=true;
4930   int nbOfCells=getNumberOfCells();
4931   for(int i=0;i<nbOfCells && ret;i++)
4932     {
4933       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4934       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4935       ret=cm.isQuadratic();
4936     }
4937   return ret;
4938 }
4939
4940 /*!
4941  * Checks if \a this mesh includes any quadratic cell.
4942  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4943  *  \throw If the coordinates array is not set.
4944  *  \throw If the nodal connectivity of cells is not defined.
4945  */
4946 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4947 {
4948   checkFullyDefined();
4949   bool ret=false;
4950   int nbOfCells=getNumberOfCells();
4951   for(int i=0;i<nbOfCells && !ret;i++)
4952     {
4953       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4954       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4955       ret=cm.isQuadratic();
4956     }
4957   return ret;
4958 }
4959
4960 /*!
4961  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4962  * this mesh, it remains unchanged.
4963  *  \throw If the coordinates array is not set.
4964  *  \throw If the nodal connectivity of cells is not defined.
4965  */
4966 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4967 {
4968   checkFullyDefined();
4969   int nbOfCells=getNumberOfCells();
4970   int delta=0;
4971   for(int i=0;i<nbOfCells;i++)
4972     {
4973       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4974       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4975       if(cm.isQuadratic())
4976         {
4977           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4978           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4979           delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4980         }
4981     }
4982   if(delta==0)
4983     return ;
4984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4985   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4986   newConn->alloc(getMeshLength()-delta,1);
4987   newConnI->alloc(nbOfCells+1,1);
4988   const int *icptr=_nodal_connec->getConstPointer();
4989   const int *iciptr=_nodal_connec_index->getConstPointer();
4990   int *ocptr=newConn->getPointer();
4991   int *ociptr=newConnI->getPointer();
4992   *ociptr=0;
4993   _types.clear();
4994   for(int i=0;i<nbOfCells;i++,ociptr++)
4995     {
4996       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4997       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4998       if(!cm.isQuadratic())
4999         {
5000           _types.insert(type);
5001           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5002           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5003         }
5004       else
5005         {
5006           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5007           _types.insert(typel);
5008           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5009           int newNbOfNodes=cml.getNumberOfNodes();
5010           *ocptr++=(int)typel;
5011           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5012           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5013         }
5014     }
5015   setConnectivity(newConn,newConnI,false);
5016 }
5017
5018 /*!
5019  * This method converts all linear cell in \a this to quadratic one.
5020  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5021  * 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)
5022  * 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.
5023  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5024  * end of the existing coordinates.
5025  * 
5026  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5027  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5028  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5029  * 
5030  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5031  *
5032  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5033  */
5034 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5035 {
5036   DataArrayInt *conn=0,*connI=0;
5037   DataArrayDouble *coords=0;
5038   std::set<INTERP_KERNEL::NormalizedCellType> types;
5039   checkFullyDefined();
5040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5041   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5042   int meshDim=getMeshDimension();
5043   switch(conversionType)
5044     {
5045     case 0:
5046       switch(meshDim)
5047         {
5048         case 1:
5049           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5050           connSafe=conn; connISafe=connI; coordsSafe=coords;
5051           break;
5052         case 2:
5053           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5054           connSafe=conn; connISafe=connI; coordsSafe=coords;
5055           break;
5056         case 3:
5057           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5058           connSafe=conn; connISafe=connI; coordsSafe=coords;
5059           break;
5060         default:
5061           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5062         }
5063       break;
5064     case 1:
5065       {
5066         switch(meshDim)
5067         {
5068         case 1:
5069           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5070           connSafe=conn; connISafe=connI; coordsSafe=coords;
5071           break;
5072         case 2:
5073           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5074           connSafe=conn; connISafe=connI; coordsSafe=coords;
5075           break;
5076         case 3:
5077           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5078           connSafe=conn; connISafe=connI; coordsSafe=coords;
5079           break;
5080         default:
5081           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5082         }
5083         break;
5084       }
5085     default:
5086       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5087     }
5088   setConnectivity(connSafe,connISafe,false);
5089   _types=types;
5090   setCoords(coordsSafe);
5091   return ret.retn();
5092 }
5093
5094 /*!
5095  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5096  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5097  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5098  */
5099 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5100 {
5101   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5105   int nbOfCells=getNumberOfCells();
5106   int nbOfNodes=getNumberOfNodes();
5107   const int *cPtr=_nodal_connec->getConstPointer();
5108   const int *icPtr=_nodal_connec_index->getConstPointer();
5109   int lastVal=0,offset=nbOfNodes;
5110   for(int i=0;i<nbOfCells;i++,icPtr++)
5111     {
5112       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5113       if(type==INTERP_KERNEL::NORM_SEG2)
5114         {
5115           types.insert(INTERP_KERNEL::NORM_SEG3);
5116           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5117           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5118           newConn->pushBackSilent(offset++);
5119           lastVal+=4;
5120           newConnI->pushBackSilent(lastVal);
5121           ret->pushBackSilent(i);
5122         }
5123       else
5124         {
5125           types.insert(type);
5126           lastVal+=(icPtr[1]-icPtr[0]);
5127           newConnI->pushBackSilent(lastVal);
5128           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5129         }
5130     }
5131   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5132   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5133   return ret.retn();
5134 }
5135
5136 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5137 {
5138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5139   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5140   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5141   //
5142   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5143   DataArrayInt *conn1D=0,*conn1DI=0;
5144   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5145   DataArrayDouble *coordsTmp=0;
5146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5147   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5148   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5149   const int *c1DPtr=conn1D->begin();
5150   const int *c1DIPtr=conn1DI->begin();
5151   int nbOfCells=getNumberOfCells();
5152   const int *cPtr=_nodal_connec->getConstPointer();
5153   const int *icPtr=_nodal_connec_index->getConstPointer();
5154   int lastVal=0;
5155   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5156     {
5157       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5158       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5159       if(!cm.isQuadratic())
5160         {
5161           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5162           types.insert(typ2); newConn->pushBackSilent(typ2);
5163           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5164           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5165             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5166           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5167           newConnI->pushBackSilent(lastVal);
5168           ret->pushBackSilent(i);
5169         }
5170       else
5171         {
5172           types.insert(typ);
5173           lastVal+=(icPtr[1]-icPtr[0]);
5174           newConnI->pushBackSilent(lastVal);
5175           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5176         }
5177     }
5178   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5179   return ret.retn();
5180 }
5181
5182 /*!
5183  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5184  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5185  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5186  */
5187 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5188 {
5189   
5190   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5191   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5192   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5193 }
5194
5195 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5196 {
5197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5198   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5199   //
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5202   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5203   //
5204   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5205   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5206   DataArrayInt *conn1D=0,*conn1DI=0;
5207   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5208   DataArrayDouble *coordsTmp=0;
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5210   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5212   const int *c1DPtr=conn1D->begin();
5213   const int *c1DIPtr=conn1DI->begin();
5214   int nbOfCells=getNumberOfCells();
5215   const int *cPtr=_nodal_connec->getConstPointer();
5216   const int *icPtr=_nodal_connec_index->getConstPointer();
5217   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5218   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5219     {
5220       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5221       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5222       if(!cm.isQuadratic())
5223         {
5224           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5225           types.insert(typ2); newConn->pushBackSilent(typ2);
5226           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5227           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5228             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5229           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5230           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5231           newConnI->pushBackSilent(lastVal);
5232           ret->pushBackSilent(i);
5233         }
5234       else
5235         {
5236           types.insert(typ);
5237           lastVal+=(icPtr[1]-icPtr[0]);
5238           newConnI->pushBackSilent(lastVal);
5239           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5240         }
5241     }
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5243   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5244   return ret.retn();
5245 }
5246
5247 /*!
5248  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5249  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5250  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5251  */
5252 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5253 {
5254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5255   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5256   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5257 }
5258
5259 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5260 {
5261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5262   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5264   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5265   //
5266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5269   //
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5271   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5272   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5273   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5274   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5277   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5281   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5282   int nbOfCells=getNumberOfCells();
5283   const int *cPtr=_nodal_connec->getConstPointer();
5284   const int *icPtr=_nodal_connec_index->getConstPointer();
5285   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5286   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5287     {
5288       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5289       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5290       if(!cm.isQuadratic())
5291         {
5292           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5293           if(typ2==INTERP_KERNEL::NORM_ERROR)
5294             {
5295               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5296               throw INTERP_KERNEL::Exception(oss.str().c_str());
5297             }
5298           types.insert(typ2); newConn->pushBackSilent(typ2);
5299           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5300           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5301             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5302           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5303             {
5304               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5305               int tmpPos=newConn->getNumberOfTuples();
5306               newConn->pushBackSilent(nodeId2);
5307               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5308             }
5309           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5310           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5311           newConnI->pushBackSilent(lastVal);
5312           ret->pushBackSilent(i);
5313         }
5314       else
5315         {
5316           types.insert(typ);
5317           lastVal+=(icPtr[1]-icPtr[0]);
5318           newConnI->pushBackSilent(lastVal);
5319           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5320         }
5321     }
5322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5324   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5325   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5326   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5327   int *c=newConn->getPointer();
5328   const int *cI(newConnI->begin());
5329   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5330     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5331   offset=coordsTmp2Safe->getNumberOfTuples();
5332   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5333     c[cI[(*elt)+1]-1]+=offset;
5334   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5335   return ret.retn();
5336 }
5337
5338 /*!
5339  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5340  * so that the number of cells remains the same. Quadratic faces are converted to
5341  * polygons. This method works only for 2D meshes in
5342  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5343  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5344  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5345  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5346  *         a polylinized edge constituting the input polygon.
5347  *  \throw If the coordinates array is not set.
5348  *  \throw If the nodal connectivity of cells is not defined.
5349  *  \throw If \a this->getMeshDimension() != 2.
5350  *  \throw If \a this->getSpaceDimension() != 2.
5351  */
5352 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5353 {
5354   checkFullyDefined();
5355   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5356     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5357   double epsa=fabs(eps);
5358   if(epsa<std::numeric_limits<double>::min())
5359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5364   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5365   revDesc1=0; revDescIndx1=0;
5366   mDesc->tessellate2DCurve(eps);
5367   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5368   setCoords(mDesc->getCoords());
5369 }
5370
5371 /*!
5372  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5373  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5374  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5375  *         a sub-divided edge.
5376  *  \throw If the coordinates array is not set.
5377  *  \throw If the nodal connectivity of cells is not defined.
5378  *  \throw If \a this->getMeshDimension() != 1.
5379  *  \throw If \a this->getSpaceDimension() != 2.
5380  */
5381 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5382 {
5383   checkFullyDefined();
5384   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5385     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5386   double epsa=fabs(eps);
5387   if(epsa<std::numeric_limits<double>::min())
5388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5389   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5390   int nbCells=getNumberOfCells();
5391   int nbNodes=getNumberOfNodes();
5392   const int *conn=_nodal_connec->getConstPointer();
5393   const int *connI=_nodal_connec_index->getConstPointer();
5394   const double *coords=_coords->getConstPointer();
5395   std::vector<double> addCoo;
5396   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5398   newConnI->alloc(nbCells+1,1);
5399   int *newConnIPtr=newConnI->getPointer();
5400   *newConnIPtr=0;
5401   int tmp1[3];
5402   INTERP_KERNEL::Node *tmp2[3];
5403   std::set<INTERP_KERNEL::NormalizedCellType> types;
5404   for(int i=0;i<nbCells;i++,newConnIPtr++)
5405     {
5406       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5407       if(cm.isQuadratic())
5408         {//assert(connI[i+1]-connI[i]-1==3)
5409           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5410           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5411           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5412           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5413           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5414           if(eac)
5415             {
5416               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5417               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5418               delete eac;
5419               newConnIPtr[1]=(int)newConn.size();
5420             }
5421           else
5422             {
5423               types.insert(INTERP_KERNEL::NORM_SEG2);
5424               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5425               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5426               newConnIPtr[1]=newConnIPtr[0]+3;
5427             }
5428         }
5429       else
5430         {
5431           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5432           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5433           newConnIPtr[1]=newConnIPtr[0]+3;
5434         }
5435     }
5436   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5437     return ;
5438   _types=types;
5439   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5440   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5441   newConnArr->alloc((int)newConn.size(),1);
5442   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5443   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5444   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5445   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5446   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5447   std::copy(addCoo.begin(),addCoo.end(),work);
5448   DataArrayDouble::SetArrayIn(newCoords,_coords);
5449   updateTime();
5450 }
5451
5452 /*!
5453  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5454  * In addition, returns an array mapping new cells to old ones. <br>
5455  * This method typically increases the number of cells in \a this mesh
5456  * but the number of nodes remains \b unchanged.
5457  * That's why the 3D splitting policies
5458  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5459  *  \param [in] policy - specifies a pattern used for splitting.
5460  * The semantic of \a policy is:
5461  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5462  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5463  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5464  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5465  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5466  *          an id of old cell producing it. The caller is to delete this array using
5467  *         decrRef() as it is no more needed. 
5468  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5469  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5470  *          and \a this->getMeshDimension() != 3. 
5471  *  \throw If \a policy is not one of the four discussed above.
5472  *  \throw If the nodal connectivity of cells is not defined.
5473  */
5474 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5475 {
5476   switch(policy)
5477     {
5478     case 0:
5479       return simplexizePol0();
5480     case 1:
5481       return simplexizePol1();
5482     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5483       return simplexizePlanarFace5();
5484     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5485       return simplexizePlanarFace6();
5486     default:
5487       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)");
5488     }
5489 }
5490
5491 /*!
5492  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5493  * - 1D: INTERP_KERNEL::NORM_SEG2
5494  * - 2D: INTERP_KERNEL::NORM_TRI3
5495  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5496  *
5497  * This method is useful for users that need to use P1 field services as
5498  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5499  * All these methods need mesh support containing only simplex cells.
5500  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5501  *  \throw If the coordinates array is not set.
5502  *  \throw If the nodal connectivity of cells is not defined.
5503  *  \throw If \a this->getMeshDimension() < 1.
5504  */
5505 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5506 {
5507   checkFullyDefined();
5508   int mdim=getMeshDimension();
5509   if(mdim<1 || mdim>3)
5510     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5511   int nbCells=getNumberOfCells();
5512   const int *conn=_nodal_connec->getConstPointer();
5513   const int *connI=_nodal_connec_index->getConstPointer();
5514   for(int i=0;i<nbCells;i++)
5515     {
5516       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5517       if(!cm.isSimplex())
5518         return false;
5519     }
5520   return true;
5521 }
5522
5523 /*!
5524  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5525  */
5526 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5527 {
5528   checkConnectivityFullyDefined();
5529   if(getMeshDimension()!=2)
5530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5531   int nbOfCells=getNumberOfCells();
5532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5533   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5534   ret->alloc(nbOfCells+nbOfCutCells,1);
5535   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5536   int *retPt=ret->getPointer();
5537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5538   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5539   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5540   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5541   int *pt=newConn->getPointer();
5542   int *ptI=newConnI->getPointer();
5543   ptI[0]=0;
5544   const int *oldc=_nodal_connec->getConstPointer();
5545   const int *ci=_nodal_connec_index->getConstPointer();
5546   for(int i=0;i<nbOfCells;i++,ci++)
5547     {
5548       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5549         {
5550           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5551                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5552           pt=std::copy(tmp,tmp+8,pt);
5553           ptI[1]=ptI[0]+4;
5554           ptI[2]=ptI[0]+8;
5555           *retPt++=i;
5556           *retPt++=i;
5557           ptI+=2;
5558         }
5559       else
5560         {
5561           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5562           ptI[1]=ptI[0]+ci[1]-ci[0];
5563           ptI++;
5564           *retPt++=i;
5565         }
5566     }
5567   _nodal_connec->decrRef();
5568   _nodal_connec=newConn.retn();
5569   _nodal_connec_index->decrRef();
5570   _nodal_connec_index=newConnI.retn();
5571   computeTypes();
5572   updateTime();
5573   return ret.retn();
5574 }
5575
5576 /*!
5577  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5578  */
5579 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5580 {
5581   checkConnectivityFullyDefined();
5582   if(getMeshDimension()!=2)
5583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5584   int nbOfCells=getNumberOfCells();
5585   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5586   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5587   ret->alloc(nbOfCells+nbOfCutCells,1);
5588   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5589   int *retPt=ret->getPointer();
5590   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5591   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5592   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5593   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5594   int *pt=newConn->getPointer();
5595   int *ptI=newConnI->getPointer();
5596   ptI[0]=0;
5597   const int *oldc=_nodal_connec->getConstPointer();
5598   const int *ci=_nodal_connec_index->getConstPointer();
5599   for(int i=0;i<nbOfCells;i++,ci++)
5600     {
5601       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5602         {
5603           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5604                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5605           pt=std::copy(tmp,tmp+8,pt);
5606           ptI[1]=ptI[0]+4;
5607           ptI[2]=ptI[0]+8;
5608           *retPt++=i;
5609           *retPt++=i;
5610           ptI+=2;
5611         }
5612       else
5613         {
5614           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5615           ptI[1]=ptI[0]+ci[1]-ci[0];
5616           ptI++;
5617           *retPt++=i;
5618         }
5619     }
5620   _nodal_connec->decrRef();
5621   _nodal_connec=newConn.retn();
5622   _nodal_connec_index->decrRef();
5623   _nodal_connec_index=newConnI.retn();
5624   computeTypes();
5625   updateTime();
5626   return ret.retn();
5627 }
5628
5629 /*!
5630  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5631  */
5632 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5633 {
5634   checkConnectivityFullyDefined();
5635   if(getMeshDimension()!=3)
5636     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5637   int nbOfCells=getNumberOfCells();
5638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5639   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5640   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5641   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5642   int *retPt=ret->getPointer();
5643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5645   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5646   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5647   int *pt=newConn->getPointer();
5648   int *ptI=newConnI->getPointer();
5649   ptI[0]=0;
5650   const int *oldc=_nodal_connec->getConstPointer();
5651   const int *ci=_nodal_connec_index->getConstPointer();
5652   for(int i=0;i<nbOfCells;i++,ci++)
5653     {
5654       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5655         {
5656           for(int j=0;j<5;j++,pt+=5,ptI++)
5657             {
5658               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5659               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5660               *retPt++=i;
5661               ptI[1]=ptI[0]+5;
5662             }
5663         }
5664       else
5665         {
5666           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5667           ptI[1]=ptI[0]+ci[1]-ci[0];
5668           ptI++;
5669           *retPt++=i;
5670         }
5671     }
5672   _nodal_connec->decrRef();
5673   _nodal_connec=newConn.retn();
5674   _nodal_connec_index->decrRef();
5675   _nodal_connec_index=newConnI.retn();
5676   computeTypes();
5677   updateTime();
5678   return ret.retn();
5679 }
5680
5681 /*!
5682  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5683  */
5684 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5685 {
5686   checkConnectivityFullyDefined();
5687   if(getMeshDimension()!=3)
5688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5689   int nbOfCells=getNumberOfCells();
5690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5691   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5692   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5693   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5694   int *retPt=ret->getPointer();
5695   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5697   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5698   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5699   int *pt=newConn->getPointer();
5700   int *ptI=newConnI->getPointer();
5701   ptI[0]=0;
5702   const int *oldc=_nodal_connec->getConstPointer();
5703   const int *ci=_nodal_connec_index->getConstPointer();
5704   for(int i=0;i<nbOfCells;i++,ci++)
5705     {
5706       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5707         {
5708           for(int j=0;j<6;j++,pt+=5,ptI++)
5709             {
5710               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5711               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5712               *retPt++=i;
5713               ptI[1]=ptI[0]+5;
5714             }
5715         }
5716       else
5717         {
5718           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5719           ptI[1]=ptI[0]+ci[1]-ci[0];
5720           ptI++;
5721           *retPt++=i;
5722         }
5723     }
5724   _nodal_connec->decrRef();
5725   _nodal_connec=newConn.retn();
5726   _nodal_connec_index->decrRef();
5727   _nodal_connec_index=newConnI.retn();
5728   computeTypes();
5729   updateTime();
5730   return ret.retn();
5731 }
5732
5733 /*!
5734  * This private method is used to subdivide edges of a mesh with meshdim==2. If 'this' has no a meshdim equal to 2 an exception will be thrown.
5735  * This method completly ignore coordinates.
5736  * @param nodeSubdived is the nodal connectivity of subdivision of edges
5737  * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5738  * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5739  * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5740  */
5741 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5742 {
5743   checkFullyDefined();
5744   if(getMeshDimension()!=2)
5745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5746   int nbOfCells=getNumberOfCells();
5747   int *connI=_nodal_connec_index->getPointer();
5748   int newConnLgth=0;
5749   for(int i=0;i<nbOfCells;i++,connI++)
5750     {
5751       int offset=descIndex[i];
5752       int nbOfEdges=descIndex[i+1]-offset;
5753       //
5754       bool ddirect=desc[offset+nbOfEdges-1]>0;
5755       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5756       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5757       for(int j=0;j<nbOfEdges;j++)
5758         {
5759           bool direct=desc[offset+j]>0;
5760           int edgeId=std::abs(desc[offset+j])-1;
5761           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5762             {
5763               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5764               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5765               int ref2=direct?id1:id2;
5766               if(ref==ref2)
5767                 {
5768                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5769                   newConnLgth+=nbOfSubNodes-1;
5770                   ref=direct?id2:id1;
5771                 }
5772               else
5773                 {
5774                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5775                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5776                 }
5777             }
5778           else
5779             {
5780               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5781             }
5782         }
5783       newConnLgth++;//+1 is for cell type
5784       connI[1]=newConnLgth;
5785     }
5786   //
5787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5788   newConn->alloc(newConnLgth,1);
5789   int *work=newConn->getPointer();
5790   for(int i=0;i<nbOfCells;i++)
5791     {
5792       *work++=INTERP_KERNEL::NORM_POLYGON;
5793       int offset=descIndex[i];
5794       int nbOfEdges=descIndex[i+1]-offset;
5795       for(int j=0;j<nbOfEdges;j++)
5796         {
5797           bool direct=desc[offset+j]>0;
5798           int edgeId=std::abs(desc[offset+j])-1;
5799           if(direct)
5800             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5801           else
5802             {
5803               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5804               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5805               work=std::copy(it,it+nbOfSubNodes-1,work);
5806             }
5807         }
5808     }
5809   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5810   _types.clear();
5811   if(nbOfCells>0)
5812     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5813 }
5814
5815 /*!
5816  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5817  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5818  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5819  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5820  * so it can be useful to call mergeNodes() before calling this method.
5821  *  \throw If \a this->getMeshDimension() <= 1.
5822  *  \throw If the coordinates array is not set.
5823  *  \throw If the nodal connectivity of cells is not defined.
5824  */
5825 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5826 {
5827   checkFullyDefined();
5828   if(getMeshDimension()<=1)
5829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5830   int nbOfCells=getNumberOfCells();
5831   if(nbOfCells<1)
5832     return ;
5833   int initMeshLgth=getMeshLength();
5834   int *conn=_nodal_connec->getPointer();
5835   int *index=_nodal_connec_index->getPointer();
5836   int posOfCurCell=0;
5837   int newPos=0;
5838   int lgthOfCurCell;
5839   for(int i=0;i<nbOfCells;i++)
5840     {
5841       lgthOfCurCell=index[i+1]-posOfCurCell;
5842       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5843       int newLgth;
5844       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5845                                                                                                      conn+newPos+1,newLgth);
5846       conn[newPos]=newType;
5847       newPos+=newLgth+1;
5848       posOfCurCell=index[i+1];
5849       index[i+1]=newPos;
5850     }
5851   if(newPos!=initMeshLgth)
5852     _nodal_connec->reAlloc(newPos);
5853   computeTypes();
5854 }
5855
5856 /*!
5857  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5858  * A cell is considered to be oriented correctly if an angle between its
5859  * normal vector and a given vector is less than \c PI / \c 2.
5860  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5861  *         cells. 
5862  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5863  *         checked.
5864  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5865  *         is not cleared before filling in.
5866  *  \throw If \a this->getMeshDimension() != 2.
5867  *  \throw If \a this->getSpaceDimension() != 3.
5868  *
5869  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5870  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5871  */
5872 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5873 {
5874   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5875     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5876   int nbOfCells=getNumberOfCells();
5877   const int *conn=_nodal_connec->getConstPointer();
5878   const int *connI=_nodal_connec_index->getConstPointer();
5879   const double *coordsPtr=_coords->getConstPointer();
5880   for(int i=0;i<nbOfCells;i++)
5881     {
5882       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5883       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5884         {
5885           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5886           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5887             cells.push_back(i);
5888         }
5889     }
5890 }
5891
5892 /*!
5893  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5894  * considered to be oriented correctly if an angle between its normal vector and a
5895  * given vector is less than \c PI / \c 2. 
5896  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5897  *         cells. 
5898  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5899  *         checked.
5900  *  \throw If \a this->getMeshDimension() != 2.
5901  *  \throw If \a this->getSpaceDimension() != 3.
5902  *
5903  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5904  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5905  */
5906 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5907 {
5908   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5909     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5910   int nbOfCells=getNumberOfCells();
5911   int *conn=_nodal_connec->getPointer();
5912   const int *connI=_nodal_connec_index->getConstPointer();
5913   const double *coordsPtr=_coords->getConstPointer();
5914   bool isModified=false;
5915   for(int i=0;i<nbOfCells;i++)
5916     {
5917       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5918       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5919         {
5920           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5921           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5922             {
5923               isModified=true;
5924               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5925               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5926               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5927             }
5928         }
5929     }
5930   if(isModified)
5931     _nodal_connec->declareAsNew();
5932   updateTime();
5933 }
5934
5935 /*!
5936  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5937  * oriented facets. The normal vector of the facet should point out of the cell.
5938  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5939  *         is not cleared before filling in.
5940  *  \throw If \a this->getMeshDimension() != 3.
5941  *  \throw If \a this->getSpaceDimension() != 3.
5942  *  \throw If the coordinates array is not set.
5943  *  \throw If the nodal connectivity of cells is not defined.
5944  *
5945  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5946  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5947  */
5948 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5949 {
5950   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5951     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5952   int nbOfCells=getNumberOfCells();
5953   const int *conn=_nodal_connec->getConstPointer();
5954   const int *connI=_nodal_connec_index->getConstPointer();
5955   const double *coordsPtr=_coords->getConstPointer();
5956   for(int i=0;i<nbOfCells;i++)
5957     {
5958       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5959       if(type==INTERP_KERNEL::NORM_POLYHED)
5960         {
5961           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5962             cells.push_back(i);
5963         }
5964     }
5965 }
5966
5967 /*!
5968  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5969  * out of the cell. 
5970  *  \throw If \a this->getMeshDimension() != 3.
5971  *  \throw If \a this->getSpaceDimension() != 3.
5972  *  \throw If the coordinates array is not set.
5973  *  \throw If the nodal connectivity of cells is not defined.
5974  *  \throw If the reparation fails.
5975  *
5976  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5977  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5978  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5979  */
5980 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5981 {
5982   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5983     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5984   int nbOfCells=getNumberOfCells();
5985   int *conn=_nodal_connec->getPointer();
5986   const int *connI=_nodal_connec_index->getConstPointer();
5987   const double *coordsPtr=_coords->getConstPointer();
5988   for(int i=0;i<nbOfCells;i++)
5989     {
5990       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5991       if(type==INTERP_KERNEL::NORM_POLYHED)
5992         {
5993           try
5994             {
5995               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5996                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5997             }
5998           catch(INTERP_KERNEL::Exception& e)
5999             {
6000               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6001               throw INTERP_KERNEL::Exception(oss.str().c_str());
6002             }
6003         }
6004     }
6005   updateTime();
6006 }
6007
6008 /*!
6009  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6010  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6011  * according to which the first facet of the cell should be oriented to have the normal vector
6012  * pointing out of cell.
6013  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6014  *         cells. The caller is to delete this array using decrRef() as it is no more
6015  *         needed. 
6016  *  \throw If \a this->getMeshDimension() != 3.
6017  *  \throw If \a this->getSpaceDimension() != 3.
6018  *  \throw If the coordinates array is not set.
6019  *  \throw If the nodal connectivity of cells is not defined.
6020  *
6021  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6022  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6023  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6024  */
6025 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6026 {
6027   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6028   if(getMeshDimension()!=3)
6029     throw INTERP_KERNEL::Exception(msg);
6030   int spaceDim=getSpaceDimension();
6031   if(spaceDim!=3)
6032     throw INTERP_KERNEL::Exception(msg);
6033   //
6034   int nbOfCells=getNumberOfCells();
6035   int *conn=_nodal_connec->getPointer();
6036   const int *connI=_nodal_connec_index->getConstPointer();
6037   const double *coo=getCoords()->getConstPointer();
6038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6039   for(int i=0;i<nbOfCells;i++)
6040     {
6041       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6042       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6043         {
6044           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6045             {
6046               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6047               cells->pushBackSilent(i);
6048             }
6049         }
6050     }
6051   return cells.retn();
6052 }
6053
6054 /*!
6055  * This method is a faster method to correct orientation of all 3D cells in \a this.
6056  * 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.
6057  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6058  * 
6059  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6060  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6061  */
6062 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6063 {
6064   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6065     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6066   int nbOfCells=getNumberOfCells();
6067   int *conn=_nodal_connec->getPointer();
6068   const int *connI=_nodal_connec_index->getConstPointer();
6069   const double *coordsPtr=_coords->getConstPointer();
6070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6071   for(int i=0;i<nbOfCells;i++)
6072     {
6073       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6074       switch(type)
6075         {
6076         case INTERP_KERNEL::NORM_TETRA4:
6077           {
6078             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6079               {
6080                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6081                 ret->pushBackSilent(i);
6082               }
6083             break;
6084           }
6085         case INTERP_KERNEL::NORM_PYRA5:
6086           {
6087             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6088               {
6089                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6090                 ret->pushBackSilent(i);
6091               }
6092             break;
6093           }
6094         case INTERP_KERNEL::NORM_PENTA6:
6095         case INTERP_KERNEL::NORM_HEXA8:
6096         case INTERP_KERNEL::NORM_HEXGP12:
6097           {
6098             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6099               {
6100                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6101                 ret->pushBackSilent(i);
6102               }
6103             break;
6104           }
6105         case INTERP_KERNEL::NORM_POLYHED:
6106           {
6107             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6108               {
6109                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6110                 ret->pushBackSilent(i);
6111               }
6112             break;
6113           }
6114         default:
6115           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 !");
6116         }
6117     }
6118   updateTime();
6119   return ret.retn();
6120 }
6121
6122 /*!
6123  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6124  * If it is not the case an exception will be thrown.
6125  * This method is fast because the first cell of 'this' is used to compute the plane.
6126  * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6127  * @param pos output of size at least 3 used to store a point owned of searched plane.
6128  */
6129 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6130 {
6131   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6132     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6133   const int *conn=_nodal_connec->getConstPointer();
6134   const int *connI=_nodal_connec_index->getConstPointer();
6135   const double *coordsPtr=_coords->getConstPointer();
6136   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6137   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6138 }
6139
6140 /*!
6141  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6142  * cells. Currently cells of the following types are treated:
6143  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6144  * For a cell of other type an exception is thrown.
6145  * Space dimension of a 2D mesh can be either 2 or 3.
6146  * The Edge Ratio of a cell \f$t\f$ is: 
6147  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6148  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6149  *  the smallest edge lengths of \f$t\f$.
6150  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6151  *          cells and one time, lying on \a this mesh. The caller is to delete this
6152  *          field using decrRef() as it is no more needed. 
6153  *  \throw If the coordinates array is not set.
6154  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6155  *  \throw If the connectivity data array has more than one component.
6156  *  \throw If the connectivity data array has a named component.
6157  *  \throw If the connectivity index data array has more than one component.
6158  *  \throw If the connectivity index data array has a named component.
6159  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6160  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6161  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6162  */
6163 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6164 {
6165   checkCoherency();
6166   int spaceDim=getSpaceDimension();
6167   int meshDim=getMeshDimension();
6168   if(spaceDim!=2 && spaceDim!=3)
6169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6170   if(meshDim!=2 && meshDim!=3)
6171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6172   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6173   ret->setMesh(this);
6174   int nbOfCells=getNumberOfCells();
6175   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6176   arr->alloc(nbOfCells,1);
6177   double *pt=arr->getPointer();
6178   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6179   const int *conn=_nodal_connec->getConstPointer();
6180   const int *connI=_nodal_connec_index->getConstPointer();
6181   const double *coo=_coords->getConstPointer();
6182   double tmp[12];
6183   for(int i=0;i<nbOfCells;i++,pt++)
6184     {
6185       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6186       switch(t)
6187         {
6188           case INTERP_KERNEL::NORM_TRI3:
6189             {
6190               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6191               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6192               break;
6193             }
6194           case INTERP_KERNEL::NORM_QUAD4:
6195             {
6196               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6197               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6198               break;
6199             }
6200           case INTERP_KERNEL::NORM_TETRA4:
6201             {
6202               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6203               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6204               break;
6205             }
6206         default:
6207           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6208         }
6209       conn+=connI[i+1]-connI[i];
6210     }
6211   ret->setName("EdgeRatio");
6212   ret->synchronizeTimeWithSupport();
6213   return ret.retn();
6214 }
6215
6216 /*!
6217  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6218  * cells. Currently cells of the following types are treated:
6219  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6220  * For a cell of other type an exception is thrown.
6221  * Space dimension of a 2D mesh can be either 2 or 3.
6222  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6223  *          cells and one time, lying on \a this mesh. The caller is to delete this
6224  *          field using decrRef() as it is no more needed. 
6225  *  \throw If the coordinates array is not set.
6226  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6227  *  \throw If the connectivity data array has more than one component.
6228  *  \throw If the connectivity data array has a named component.
6229  *  \throw If the connectivity index data array has more than one component.
6230  *  \throw If the connectivity index data array has a named component.
6231  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6232  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6233  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6234  */
6235 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6236 {
6237   checkCoherency();
6238   int spaceDim=getSpaceDimension();
6239   int meshDim=getMeshDimension();
6240   if(spaceDim!=2 && spaceDim!=3)
6241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6242   if(meshDim!=2 && meshDim!=3)
6243     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6244   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6245   ret->setMesh(this);
6246   int nbOfCells=getNumberOfCells();
6247   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6248   arr->alloc(nbOfCells,1);
6249   double *pt=arr->getPointer();
6250   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6251   const int *conn=_nodal_connec->getConstPointer();
6252   const int *connI=_nodal_connec_index->getConstPointer();
6253   const double *coo=_coords->getConstPointer();
6254   double tmp[12];
6255   for(int i=0;i<nbOfCells;i++,pt++)
6256     {
6257       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6258       switch(t)
6259         {
6260           case INTERP_KERNEL::NORM_TRI3:
6261             {
6262               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6263               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6264               break;
6265             }
6266           case INTERP_KERNEL::NORM_QUAD4:
6267             {
6268               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6269               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6270               break;
6271             }
6272           case INTERP_KERNEL::NORM_TETRA4:
6273             {
6274               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6275               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6276               break;
6277             }
6278         default:
6279           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6280         }
6281       conn+=connI[i+1]-connI[i];
6282     }
6283   ret->setName("AspectRatio");
6284   ret->synchronizeTimeWithSupport();
6285   return ret.retn();
6286 }
6287
6288 /*!
6289  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6290  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6291  * treated: INTERP_KERNEL::NORM_QUAD4.
6292  * For a cell of other type an exception is thrown.
6293  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6294  *          cells and one time, lying on \a this mesh. The caller is to delete this
6295  *          field using decrRef() as it is no more needed. 
6296  *  \throw If the coordinates array is not set.
6297  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6298  *  \throw If the connectivity data array has more than one component.
6299  *  \throw If the connectivity data array has a named component.
6300  *  \throw If the connectivity index data array has more than one component.
6301  *  \throw If the connectivity index data array has a named component.
6302  *  \throw If \a this->getMeshDimension() != 2.
6303  *  \throw If \a this->getSpaceDimension() != 3.
6304  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6305  */
6306 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6307 {
6308   checkCoherency();
6309   int spaceDim=getSpaceDimension();
6310   int meshDim=getMeshDimension();
6311   if(spaceDim!=3)
6312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6313   if(meshDim!=2)
6314     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6315   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6316   ret->setMesh(this);
6317   int nbOfCells=getNumberOfCells();
6318   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6319   arr->alloc(nbOfCells,1);
6320   double *pt=arr->getPointer();
6321   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6322   const int *conn=_nodal_connec->getConstPointer();
6323   const int *connI=_nodal_connec_index->getConstPointer();
6324   const double *coo=_coords->getConstPointer();
6325   double tmp[12];
6326   for(int i=0;i<nbOfCells;i++,pt++)
6327     {
6328       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6329       switch(t)
6330         {
6331           case INTERP_KERNEL::NORM_QUAD4:
6332             {
6333               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6334               *pt=INTERP_KERNEL::quadWarp(tmp);
6335               break;
6336             }
6337         default:
6338           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6339         }
6340       conn+=connI[i+1]-connI[i];
6341     }
6342   ret->setName("Warp");
6343   ret->synchronizeTimeWithSupport();
6344   return ret.retn();
6345 }
6346
6347
6348 /*!
6349  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6350  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6351  * treated: INTERP_KERNEL::NORM_QUAD4.
6352  * For a cell of other type an exception is thrown.
6353  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6354  *          cells and one time, lying on \a this mesh. The caller is to delete this
6355  *          field using decrRef() as it is no more needed. 
6356  *  \throw If the coordinates array is not set.
6357  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6358  *  \throw If the connectivity data array has more than one component.
6359  *  \throw If the connectivity data array has a named component.
6360  *  \throw If the connectivity index data array has more than one component.
6361  *  \throw If the connectivity index data array has a named component.
6362  *  \throw If \a this->getMeshDimension() != 2.
6363  *  \throw If \a this->getSpaceDimension() != 3.
6364  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6365  */
6366 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6367 {
6368   checkCoherency();
6369   int spaceDim=getSpaceDimension();
6370   int meshDim=getMeshDimension();
6371   if(spaceDim!=3)
6372     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6373   if(meshDim!=2)
6374     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6375   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6376   ret->setMesh(this);
6377   int nbOfCells=getNumberOfCells();
6378   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6379   arr->alloc(nbOfCells,1);
6380   double *pt=arr->getPointer();
6381   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6382   const int *conn=_nodal_connec->getConstPointer();
6383   const int *connI=_nodal_connec_index->getConstPointer();
6384   const double *coo=_coords->getConstPointer();
6385   double tmp[12];
6386   for(int i=0;i<nbOfCells;i++,pt++)
6387     {
6388       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6389       switch(t)
6390         {
6391           case INTERP_KERNEL::NORM_QUAD4:
6392             {
6393               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6394               *pt=INTERP_KERNEL::quadSkew(tmp);
6395               break;
6396             }
6397         default:
6398           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6399         }
6400       conn+=connI[i+1]-connI[i];
6401     }
6402   ret->setName("Skew");
6403   ret->synchronizeTimeWithSupport();
6404   return ret.retn();
6405 }
6406
6407 /*!
6408  * This method aggregate the bbox of each cell and put it into bbox parameter.
6409  * @param bbox out parameter of size 2*spacedim*nbOfcells.
6410  */
6411 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6412 {
6413   int spaceDim=getSpaceDimension();
6414   int nbOfCells=getNumberOfCells();
6415   bbox.resize(2*nbOfCells*spaceDim);
6416   for(int i=0;i<nbOfCells*spaceDim;i++)
6417     {
6418       bbox[2*i]=std::numeric_limits<double>::max();
6419       bbox[2*i+1]=-std::numeric_limits<double>::max();
6420     }
6421   const double *coordsPtr=_coords->getConstPointer();
6422   const int *conn=_nodal_connec->getConstPointer();
6423   const int *connI=_nodal_connec_index->getConstPointer();
6424   for(int i=0;i<nbOfCells;i++)
6425     {
6426       int offset=connI[i]+1;
6427       int nbOfNodesForCell=connI[i+1]-offset;
6428       for(int j=0;j<nbOfNodesForCell;j++)
6429         {
6430           int nodeId=conn[offset+j];
6431           if(nodeId>=0)
6432             for(int k=0;k<spaceDim;k++)
6433               {
6434                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6435                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6436               }
6437         }
6438     }
6439 }
6440
6441 /// @cond INTERNAL
6442
6443 namespace ParaMEDMEMImpl
6444 {
6445   class ConnReader
6446   {
6447   public:
6448     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6449     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6450   private:
6451     const int *_conn;
6452     int _val;
6453   };
6454
6455   class ConnReader2
6456   {
6457   public:
6458     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6459     bool operator() (const int& pos) { return _conn[pos]==_val; }
6460   private:
6461     const int *_conn;
6462     int _val;
6463   };
6464 }
6465
6466 /// @endcond
6467
6468 /*!
6469  * This method expects that 'this' is sorted by types. If not an exception will be thrown.
6470  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6471  * 'this' is composed in cell types.
6472  * The returned array is of size 3*n where n is the number of different types present in 'this'. 
6473  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6474  * This parameter is kept only for compatibility with other methode listed above.
6475  */
6476 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6477 {
6478   checkConnectivityFullyDefined();
6479   const int *conn=_nodal_connec->getConstPointer();
6480   const int *connI=_nodal_connec_index->getConstPointer();
6481   const int *work=connI;
6482   int nbOfCells=getNumberOfCells();
6483   std::size_t n=getAllTypes().size();
6484   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6485   std::set<INTERP_KERNEL::NormalizedCellType> types;
6486   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6487     {
6488       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6489       if(types.find(typ)!=types.end())
6490         {
6491           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6492           oss << " is not contiguous !";
6493           throw INTERP_KERNEL::Exception(oss.str().c_str());
6494         }
6495       types.insert(typ);
6496       ret[3*i]=typ;
6497       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6498       ret[3*i+1]=(int)std::distance(work,work2);
6499       work=work2;
6500     }
6501   return ret;
6502 }
6503
6504 /*!
6505  * This method is used to check that this has contiguous cell type in same order than described in 'code'.
6506  * only for types cell, type node is not managed.
6507  * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
6508  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6509  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6510  * If 2 or more same geometric type is in 'code' and exception is thrown too.
6511  *
6512  * This method firstly checks
6513  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6514  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6515  * an exception is thrown too.
6516  * 
6517  * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
6518  * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown 
6519  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6520  */
6521 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6522 {
6523   if(code.empty())
6524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6525   std::size_t sz=code.size();
6526   std::size_t n=sz/3;
6527   if(sz%3!=0)
6528     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6529   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6530   int nb=0;
6531   for(std::size_t i=0;i<n;i++)
6532     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6533       {
6534         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6535         nb+=code[3*i+1];
6536         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6537           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6538       }
6539   if(types.size()!=n)
6540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6541   if(idsPerType.empty())
6542     {
6543       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6544         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6545       if(types.size()==_types.size())
6546         return 0;
6547     }
6548   DataArrayInt *ret=DataArrayInt::New();
6549   ret->alloc(nb,1);
6550   int *retPtr=ret->getPointer();
6551   const int *connI=_nodal_connec_index->getConstPointer();
6552   const int *conn=_nodal_connec->getConstPointer();
6553   int nbOfCells=getNumberOfCells();
6554   const int *i=connI;
6555   int kk=0;
6556   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6557     {
6558       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6559       int offset=(int)std::distance(connI,i);
6560       if(code[3*kk+2]==-1)
6561         {
6562           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6563           std::size_t pos2=std::distance(i,j);
6564           for(std::size_t k=0;k<pos2;k++)
6565             *retPtr++=(int)k+offset;
6566           i=j;
6567         }
6568       else
6569         {
6570           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6571                                 retPtr,std::bind2nd(std::plus<int>(),offset));
6572         }
6573     }
6574   return ret;
6575 }
6576
6577 /*!
6578  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6579  * 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.
6580  * 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.
6581  * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
6582  * 
6583  * @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.
6584  * @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,
6585  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6586  * @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.
6587  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6588  * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
6589  */
6590 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6591 {
6592   if(profile->getNumberOfComponents()!=1)
6593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6594   checkConnectivityFullyDefined();
6595   const int *conn=_nodal_connec->getConstPointer();
6596   const int *connI=_nodal_connec_index->getConstPointer();
6597   int nbOfCells=getNumberOfCells();
6598   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6599   std::vector<int> typeRangeVals(1);
6600   for(const int *i=connI;i!=connI+nbOfCells;)
6601     {
6602       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6603       if(std::find(types.begin(),types.end(),curType)!=types.end())
6604         {
6605           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6606         }
6607       types.push_back(curType);
6608       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6609       typeRangeVals.push_back((int)std::distance(connI,i));
6610     }
6611   //
6612   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6613   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6614   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6615   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6616   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6617   //
6618   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6619   code.resize(3*nbOfCastsFinal);
6620   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6621   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6622   for(int i=0;i<nbOfCastsFinal;i++)
6623     {
6624       int castId=castsPresent->getIJ(i,0);
6625       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6626       idsInPflPerType2.push_back(tmp3);
6627       code[3*i]=(int)types[castId];
6628       code[3*i+1]=tmp3->getNumberOfTuples();
6629       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6630       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6631         {
6632           tmp4->copyStringInfoFrom(*profile);
6633           idsPerType2.push_back(tmp4);
6634           code[3*i+2]=(int)idsPerType2.size()-1;
6635         }
6636       else
6637         {
6638           code[3*i+2]=-1;
6639         }
6640     }
6641   std::size_t sz2=idsInPflPerType2.size();
6642   idsInPflPerType.resize(sz2);
6643   for(std::size_t i=0;i<sz2;i++)
6644     {
6645       DataArrayInt *locDa=idsInPflPerType2[i];
6646       locDa->incrRef();
6647       idsInPflPerType[i]=locDa;
6648     }
6649   std::size_t sz=idsPerType2.size();
6650   idsPerType.resize(sz);
6651   for(std::size_t i=0;i<sz;i++)
6652     {
6653       DataArrayInt *locDa=idsPerType2[i];
6654       locDa->incrRef();
6655       idsPerType[i]=locDa;
6656     }
6657 }
6658
6659 /*!
6660  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6661  * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6662  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6663  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
6664  */
6665 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6666 {
6667   checkFullyDefined();
6668   nM1LevMesh->checkFullyDefined();
6669   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6670     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6671   if(_coords!=nM1LevMesh->getCoords())
6672     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6675   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6677   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6678   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6679   tmp->setConnectivity(tmp0,tmp1);
6680   tmp->renumberCells(ret0->getConstPointer(),false);
6681   revDesc=tmp->getNodalConnectivity();
6682   revDescIndx=tmp->getNodalConnectivityIndex();
6683   DataArrayInt *ret=0;
6684   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6685     {
6686       int tmp2;
6687       ret->getMaxValue(tmp2);
6688       ret->decrRef();
6689       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6690       throw INTERP_KERNEL::Exception(oss.str().c_str());
6691     }
6692   nM1LevMeshIds=ret;
6693   //
6694   revDesc->incrRef();
6695   revDescIndx->incrRef();
6696   ret1->incrRef();
6697   ret0->incrRef();
6698   meshnM1Old2New=ret0;
6699   return ret1;
6700 }
6701
6702 /*!
6703  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6704  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6705  * in "Old to New" mode.
6706  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6707  *          this array using decrRef() as it is no more needed.
6708  *  \throw If the nodal connectivity of cells is not defined.
6709  */
6710 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6711 {
6712   checkConnectivityFullyDefined();
6713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6714   renumberCells(ret->getConstPointer(),false);
6715   return ret.retn();
6716 }
6717
6718 /*!
6719  * This methods checks that cells are sorted by their types.
6720  * This method makes asumption (no check) that connectivity is correctly set before calling.
6721  */
6722 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6723 {
6724   checkFullyDefined();
6725   const int *conn=_nodal_connec->getConstPointer();
6726   const int *connI=_nodal_connec_index->getConstPointer();
6727   int nbOfCells=getNumberOfCells();
6728   std::set<INTERP_KERNEL::NormalizedCellType> types;
6729   for(const int *i=connI;i!=connI+nbOfCells;)
6730     {
6731       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6732       if(types.find(curType)!=types.end())
6733         return false;
6734       types.insert(curType);
6735       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6736     }
6737   return true;
6738 }
6739
6740 /*!
6741  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6742  * The geometric type order is specified by MED file.
6743  * 
6744  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6745  */
6746 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6747 {
6748   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6749 }
6750
6751 /*!
6752  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6753  * that the order is specified in array defined by [orderBg,orderEnd).
6754  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6755  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6756  */
6757 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6758 {
6759   checkFullyDefined();
6760   const int *conn=_nodal_connec->getConstPointer();
6761   const int *connI=_nodal_connec_index->getConstPointer();
6762   int nbOfCells=getNumberOfCells();
6763   if(nbOfCells==0)
6764     return true;
6765   int lastPos=-1;
6766   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6767   for(const int *i=connI;i!=connI+nbOfCells;)
6768     {
6769       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6770       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6771       if(isTypeExists!=orderEnd)
6772         {
6773           int pos=(int)std::distance(orderBg,isTypeExists);
6774           if(pos<=lastPos)
6775             return false;
6776           lastPos=pos;
6777           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6778         }
6779       else
6780         {
6781           if(sg.find(curType)==sg.end())
6782             {
6783               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6784               sg.insert(curType);
6785             }
6786           else
6787             return false;
6788         }
6789     }
6790   return true;
6791 }
6792
6793 /*!
6794  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6795  * 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
6796  * 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'.
6797  */
6798 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6799 {
6800   checkConnectivityFullyDefined();
6801   int nbOfCells=getNumberOfCells();
6802   const int *conn=_nodal_connec->getConstPointer();
6803   const int *connI=_nodal_connec_index->getConstPointer();
6804   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6806   tmpa->alloc(nbOfCells,1);
6807   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6808   tmpb->fillWithZero();
6809   int *tmp=tmpa->getPointer();
6810   int *tmp2=tmpb->getPointer();
6811   for(const int *i=connI;i!=connI+nbOfCells;i++)
6812     {
6813       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6814       if(where!=orderEnd)
6815         {
6816           int pos=(int)std::distance(orderBg,where);
6817           tmp2[pos]++;
6818           tmp[std::distance(connI,i)]=pos;
6819         }
6820       else
6821         {
6822           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6823           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6824           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6825           throw INTERP_KERNEL::Exception(oss.str().c_str());
6826         }
6827     }
6828   nbPerType=tmpb.retn();
6829   return tmpa.retn();
6830 }
6831
6832 /*!
6833  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in 'this'.
6834  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6835  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6836  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6837  */
6838 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6839 {
6840   DataArrayInt *nbPerType=0;
6841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6842   nbPerType->decrRef();
6843   return tmpa->buildPermArrPerLevel();
6844 }
6845
6846 /*!
6847  * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6848  * The number of cells remains unchanged after the call of this method.
6849  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6850  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6851  *
6852  * @return the array giving the correspondance old to new.
6853  */
6854 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6855 {
6856   checkFullyDefined();
6857   computeTypes();
6858   const int *conn=_nodal_connec->getConstPointer();
6859   const int *connI=_nodal_connec_index->getConstPointer();
6860   int nbOfCells=getNumberOfCells();
6861   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6862   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6863     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6864       {
6865         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6866         types.push_back(curType);
6867         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6868       }
6869   DataArrayInt *ret=DataArrayInt::New();
6870   ret->alloc(nbOfCells,1);
6871   int *retPtr=ret->getPointer();
6872   std::fill(retPtr,retPtr+nbOfCells,-1);
6873   int newCellId=0;
6874   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6875     {
6876       for(const int *i=connI;i!=connI+nbOfCells;i++)
6877         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6878           retPtr[std::distance(connI,i)]=newCellId++;
6879     }
6880   renumberCells(retPtr,false);
6881   return ret;
6882 }
6883
6884 /*!
6885  * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6886  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6887  * This method makes asumption that connectivity is correctly set before calling.
6888  */
6889 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6890 {
6891   checkFullyDefined();
6892   const int *conn=_nodal_connec->getConstPointer();
6893   const int *connI=_nodal_connec_index->getConstPointer();
6894   int nbOfCells=getNumberOfCells();
6895   std::vector<MEDCouplingUMesh *> ret;
6896   for(const int *i=connI;i!=connI+nbOfCells;)
6897     {
6898       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6899       int beginCellId=(int)std::distance(connI,i);
6900       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6901       int endCellId=(int)std::distance(connI,i);
6902       int sz=endCellId-beginCellId;
6903       int *cells=new int[sz];
6904       for(int j=0;j<sz;j++)
6905         cells[j]=beginCellId+j;
6906       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6907       delete [] cells;
6908       ret.push_back(m);
6909     }
6910   return ret;
6911 }
6912
6913 /*!
6914  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6915  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6916  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6917  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6918  * are not used here to avoid the build of big permutation array.
6919  *
6920  * \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
6921  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6922  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6923  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6924  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6925  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6926  * \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
6927  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6928  */
6929 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6930                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6931                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6932 {
6933   std::vector<const MEDCouplingUMesh *> ms2;
6934   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6935     if(*it)
6936       {
6937         (*it)->checkConnectivityFullyDefined();
6938         ms2.push_back(*it);
6939       }
6940   if(ms2.empty())
6941     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6942   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6943   int meshDim=ms2[0]->getMeshDimension();
6944   std::vector<const MEDCouplingUMesh *> m1ssm;
6945   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6946   //
6947   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6948   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6949   int fake=0,rk=0;
6950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6951   ret1->alloc(0,1); ret2->alloc(0,1);
6952   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6953     {
6954       if(meshDim!=(*it)->getMeshDimension())
6955         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6956       if(refCoo!=(*it)->getCoords())
6957         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6958       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6959       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6960       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6961       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6962         {
6963           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6964           m1ssmSingleAuto.push_back(singleCell);
6965           m1ssmSingle.push_back(singleCell);
6966           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6967         }
6968     }
6969   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6971   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6972   for(std::size_t i=0;i<m1ssm.size();i++)
6973     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6974   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6975   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6976   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6977   return ret0.retn();
6978 }
6979
6980 /*!
6981  * This method returns a newly created DataArrayInt instance.
6982  * This method retrieves cell ids in [begin,end) that have the type 'type'.
6983  */
6984 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6985 {
6986   checkFullyDefined();
6987   const int *conn=_nodal_connec->getConstPointer();
6988   const int *connIndex=_nodal_connec_index->getConstPointer();
6989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6990   for(const int *w=begin;w!=end;w++)
6991     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6992       ret->pushBackSilent(*w);
6993   return ret.retn();
6994 }
6995
6996 /*!
6997  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6998  * are in [0:getNumberOfCells())
6999  */
7000 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
7001 {
7002   checkFullyDefined();
7003   const int *conn=_nodal_connec->getConstPointer();
7004   const int *connI=_nodal_connec_index->getConstPointer();
7005   int nbOfCells=getNumberOfCells();
7006   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7007   int *tmp=new int[nbOfCells];
7008   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7009     {
7010       int j=0;
7011       for(const int *i=connI;i!=connI+nbOfCells;i++)
7012         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7013           tmp[std::distance(connI,i)]=j++;
7014     }
7015   DataArrayInt *ret=DataArrayInt::New();
7016   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7017   ret->copyStringInfoFrom(*da);
7018   int *retPtr=ret->getPointer();
7019   const int *daPtr=da->getConstPointer();
7020   int nbOfElems=da->getNbOfElems();
7021   for(int k=0;k<nbOfElems;k++)
7022     retPtr[k]=tmp[daPtr[k]];
7023   delete [] tmp;
7024   return ret;
7025 }
7026
7027 /*!
7028  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7029  * This method \b works \b for mesh sorted by type.
7030  * cells whose ids is in 'idsPerGeoType' array.
7031  * This method conserves coords and name of mesh.
7032  */
7033 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7034 {
7035   std::vector<int> code=getDistributionOfTypes();
7036   std::size_t nOfTypesInThis=code.size()/3;
7037   int sz=0,szOfType=0;
7038   for(std::size_t i=0;i<nOfTypesInThis;i++)
7039     {
7040       if(code[3*i]!=type)
7041         sz+=code[3*i+1];
7042       else
7043         szOfType=code[3*i+1];
7044     }
7045   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7046     if(*work<0 || *work>=szOfType)
7047       {
7048         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7049         oss << ". It should be in [0," << szOfType << ") !";
7050         throw INTERP_KERNEL::Exception(oss.str().c_str());
7051       }
7052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7053   int *idsPtr=idsTokeep->getPointer();
7054   int offset=0;
7055   for(std::size_t i=0;i<nOfTypesInThis;i++)
7056     {
7057       if(code[3*i]!=type)
7058         for(int j=0;j<code[3*i+1];j++)
7059           *idsPtr++=offset+j;
7060       else
7061         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7062       offset+=code[3*i+1];
7063     }
7064   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7065   ret->copyTinyInfoFrom(this);
7066   return ret.retn();
7067 }
7068
7069 /*!
7070  * This method returns a vector of size 'this->getNumberOfCells()'.
7071  * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
7072  */
7073 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7074 {
7075   int ncell=getNumberOfCells();
7076   std::vector<bool> ret(ncell);
7077   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7078   const int *c=getNodalConnectivity()->getConstPointer();
7079   for(int i=0;i<ncell;i++)
7080     {
7081       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7082       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7083       ret[i]=cm.isQuadratic();
7084     }
7085   return ret;
7086 }
7087
7088 /*!
7089  * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
7090  */
7091 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7092 {
7093   if(other->getType()!=UNSTRUCTURED)
7094     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7095   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7096   return MergeUMeshes(this,otherC);
7097 }
7098
7099 /*!
7100  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7101  * computed by averaging coordinates of cell nodes, so this method is not a right
7102  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7103  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7104  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7105  *          components. The caller is to delete this array using decrRef() as it is
7106  *          no more needed.
7107  *  \throw If the coordinates array is not set.
7108  *  \throw If the nodal connectivity of cells is not defined.
7109  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7110  */
7111 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7112 {
7113   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7114   int spaceDim=getSpaceDimension();
7115   int nbOfCells=getNumberOfCells();
7116   ret->alloc(nbOfCells,spaceDim);
7117   ret->copyStringInfoFrom(*getCoords());
7118   double *ptToFill=ret->getPointer();
7119   const int *nodal=_nodal_connec->getConstPointer();
7120   const int *nodalI=_nodal_connec_index->getConstPointer();
7121   const double *coor=_coords->getConstPointer();
7122   for(int i=0;i<nbOfCells;i++)
7123     {
7124       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7125       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7126       ptToFill+=spaceDim;
7127     }
7128   return ret.retn();
7129 }
7130
7131 /*!
7132  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7133  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7134  * 
7135  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7136  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7137  * 
7138  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7139  * \throw If \a this is not fully defined (coordinates and connectivity)
7140  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7141  */
7142 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7143 {
7144   checkFullyDefined();
7145   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7146   int spaceDim=getSpaceDimension();
7147   int nbOfCells=getNumberOfCells();
7148   int nbOfNodes=getNumberOfNodes();
7149   ret->alloc(nbOfCells,spaceDim);
7150   double *ptToFill=ret->getPointer();
7151   const int *nodal=_nodal_connec->getConstPointer();
7152   const int *nodalI=_nodal_connec_index->getConstPointer();
7153   const double *coor=_coords->getConstPointer();
7154   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7155     {
7156       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7157       std::fill(ptToFill,ptToFill+spaceDim,0.);
7158       if(type!=INTERP_KERNEL::NORM_POLYHED)
7159         {
7160           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7161             {
7162               if(*conn>=0 && *conn<nbOfNodes)
7163                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7164               else
7165                 {
7166                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7167                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7168                 }
7169             }
7170           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7171           if(nbOfNodesInCell>0)
7172             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7173           else
7174             {
7175               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7176               throw INTERP_KERNEL::Exception(oss.str().c_str());
7177             }
7178         }
7179       else
7180         {
7181           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7182           s.erase(-1);
7183           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7184             {
7185               if(*it>=0 && *it<nbOfNodes)
7186                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7187               else
7188                 {
7189                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7190                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7191                 }
7192             }
7193           if(!s.empty())
7194             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7195           else
7196             {
7197               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7198               throw INTERP_KERNEL::Exception(oss.str().c_str());
7199             }
7200         }
7201     }
7202   return ret.retn();
7203 }
7204
7205 /*!
7206  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7207  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7208  * are specified via an array of cell ids. 
7209  *  \warning Validity of the specified cell ids is not checked! 
7210  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7211  *  \param [in] begin - an array of cell ids of interest.
7212  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7213  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7214  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7215  *          caller is to delete this array using decrRef() as it is no more needed. 
7216  *  \throw If the coordinates array is not set.
7217  *  \throw If the nodal connectivity of cells is not defined.
7218  *
7219  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7220  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7221  */
7222 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7223 {
7224   DataArrayDouble *ret=DataArrayDouble::New();
7225   int spaceDim=getSpaceDimension();
7226   int nbOfTuple=(int)std::distance(begin,end);
7227   ret->alloc(nbOfTuple,spaceDim);
7228   double *ptToFill=ret->getPointer();
7229   double *tmp=new double[spaceDim];
7230   const int *nodal=_nodal_connec->getConstPointer();
7231   const int *nodalI=_nodal_connec_index->getConstPointer();
7232   const double *coor=_coords->getConstPointer();
7233   for(const int *w=begin;w!=end;w++)
7234     {
7235       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7236       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7237       ptToFill+=spaceDim;
7238     }
7239   delete [] tmp;
7240   return ret;
7241 }
7242
7243 /*!
7244  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7245  * 
7246  */
7247 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7248 {
7249   if(!da)
7250     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7251   da->checkAllocated();
7252   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7253   ret->setCoords(da);
7254   int nbOfTuples=da->getNumberOfTuples();
7255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7256   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7257   c->alloc(2*nbOfTuples,1);
7258   cI->alloc(nbOfTuples+1,1);
7259   int *cp=c->getPointer();
7260   int *cip=cI->getPointer();
7261   *cip++=0;
7262   for(int i=0;i<nbOfTuples;i++)
7263     {
7264       *cp++=INTERP_KERNEL::NORM_POINT1;
7265       *cp++=i;
7266       *cip++=2*(i+1);
7267     }
7268   ret->setConnectivity(c,cI,true);
7269   return ret.retn();
7270 }
7271 /*!
7272  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7273  * Cells and nodes of
7274  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7275  *  \param [in] mesh1 - the first mesh.
7276  *  \param [in] mesh2 - the second mesh.
7277  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7278  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7279  *          is no more needed.
7280  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7281  *  \throw If the coordinates array is not set in none of the meshes.
7282  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7283  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7284  */
7285 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7286 {
7287   std::vector<const MEDCouplingUMesh *> tmp(2);
7288   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7289   return MergeUMeshes(tmp);
7290 }
7291
7292 /*!
7293  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7294  * Cells and nodes of
7295  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7296  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7297  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7298  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7299  *          is no more needed.
7300  *  \throw If \a a.size() == 0.
7301  *  \throw If \a a[ *i* ] == NULL.
7302  *  \throw If the coordinates array is not set in none of the meshes.
7303  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7304  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7305 */
7306 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7307 {
7308   std::size_t sz=a.size();
7309   if(sz==0)
7310     return MergeUMeshesLL(a);
7311   for(std::size_t ii=0;ii<sz;ii++)
7312     if(!a[ii])
7313       {
7314         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7315         throw INTERP_KERNEL::Exception(oss.str().c_str());
7316       }
7317   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7318   std::vector< const MEDCouplingUMesh * > aa(sz);
7319   int spaceDim=-3;
7320   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7321     {
7322       const MEDCouplingUMesh *cur=a[i];
7323       const DataArrayDouble *coo=cur->getCoords();
7324       if(coo)
7325         spaceDim=coo->getNumberOfComponents();
7326     }
7327   if(spaceDim==-3)
7328     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7329   for(std::size_t i=0;i<sz;i++)
7330     {
7331       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7332       aa[i]=bb[i];
7333     }
7334   return MergeUMeshesLL(aa);
7335 }
7336
7337 /// @cond INTERNAL
7338
7339 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7340 {
7341   if(a.empty())
7342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7343   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7344   int meshDim=(*it)->getMeshDimension();
7345   int nbOfCells=(*it)->getNumberOfCells();
7346   int meshLgth=(*it++)->getMeshLength();
7347   for(;it!=a.end();it++)
7348     {
7349       if(meshDim!=(*it)->getMeshDimension())
7350         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7351       nbOfCells+=(*it)->getNumberOfCells();
7352       meshLgth+=(*it)->getMeshLength();
7353     }
7354   std::vector<const MEDCouplingPointSet *> aps(a.size());
7355   std::copy(a.begin(),a.end(),aps.begin());
7356   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7357   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7358   ret->setCoords(pts);
7359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7360   c->alloc(meshLgth,1);
7361   int *cPtr=c->getPointer();
7362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7363   cI->alloc(nbOfCells+1,1);
7364   int *cIPtr=cI->getPointer();
7365   *cIPtr++=0;
7366   int offset=0;
7367   int offset2=0;
7368   for(it=a.begin();it!=a.end();it++)
7369     {
7370       int curNbOfCell=(*it)->getNumberOfCells();
7371       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7372       const int *curC=(*it)->_nodal_connec->getConstPointer();
7373       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7374       for(int j=0;j<curNbOfCell;j++)
7375         {
7376           const int *src=curC+curCI[j];
7377           *cPtr++=*src++;
7378           for(;src!=curC+curCI[j+1];src++,cPtr++)
7379             {
7380               if(*src!=-1)
7381                 *cPtr=*src+offset2;
7382               else
7383                 *cPtr=-1;
7384             }
7385         }
7386       offset+=curCI[curNbOfCell];
7387       offset2+=(*it)->getNumberOfNodes();
7388     }
7389   //
7390   ret->setConnectivity(c,cI,true);
7391   return ret.retn();
7392 }
7393
7394 /// @endcond
7395
7396 /*!
7397  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7398  * dimension and sharing the node coordinates array.
7399  * All cells of the first mesh precede all cells of the second mesh
7400  * within the result mesh. 
7401  *  \param [in] mesh1 - the first mesh.
7402  *  \param [in] mesh2 - the second mesh.
7403  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7404  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7405  *          is no more needed.
7406  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7407  *  \throw If the meshes do not share the node coordinates array.
7408  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7409  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7410  */
7411 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7412 {
7413   std::vector<const MEDCouplingUMesh *> tmp(2);
7414   tmp[0]=mesh1; tmp[1]=mesh2;
7415   return MergeUMeshesOnSameCoords(tmp);
7416 }
7417
7418 /*!
7419  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7420  * dimension and sharing the node coordinates array.
7421  * All cells of the *i*-th mesh precede all cells of the
7422  * (*i*+1)-th mesh within the result mesh.
7423  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7424  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7425  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7426  *          is no more needed.
7427  *  \throw If \a a.size() == 0.
7428  *  \throw If \a a[ *i* ] == NULL.
7429  *  \throw If the meshes do not share the node coordinates array.
7430  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7431  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7432  */
7433 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7434 {
7435   if(meshes.empty())
7436     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7437   for(std::size_t ii=0;ii<meshes.size();ii++)
7438     if(!meshes[ii])
7439       {
7440         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7441         throw INTERP_KERNEL::Exception(oss.str().c_str());
7442       }
7443   const DataArrayDouble *coords=meshes.front()->getCoords();
7444   int meshDim=meshes.front()->getMeshDimension();
7445   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7446   int meshLgth=0;
7447   int meshIndexLgth=0;
7448   for(;iter!=meshes.end();iter++)
7449     {
7450       if(coords!=(*iter)->getCoords())
7451         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7452       if(meshDim!=(*iter)->getMeshDimension())
7453         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7454       meshLgth+=(*iter)->getMeshLength();
7455       meshIndexLgth+=(*iter)->getNumberOfCells();
7456     }
7457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7458   nodal->alloc(meshLgth,1);
7459   int *nodalPtr=nodal->getPointer();
7460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7461   nodalIndex->alloc(meshIndexLgth+1,1);
7462   int *nodalIndexPtr=nodalIndex->getPointer();
7463   int offset=0;
7464   for(iter=meshes.begin();iter!=meshes.end();iter++)
7465     {
7466       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7467       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7468       int nbOfCells=(*iter)->getNumberOfCells();
7469       int meshLgth2=(*iter)->getMeshLength();
7470       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7471       if(iter!=meshes.begin())
7472         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7473       else
7474         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7475       offset+=meshLgth2;
7476     }
7477   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7478   ret->setName("merge");
7479   ret->setMeshDimension(meshDim);
7480   ret->setConnectivity(nodal,nodalIndex,true);
7481   ret->setCoords(coords);
7482   return ret;
7483 }
7484
7485 /*!
7486  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7487  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7488  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7489  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7490  * New" mode are returned for each input mesh.
7491  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7492  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7493  *          valid values [0,1,2], see zipConnectivityTraducer().
7494  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7495  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7496  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7497  *          no more needed.
7498  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7499  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7500  *          is no more needed.
7501  *  \throw If \a meshes.size() == 0.
7502  *  \throw If \a meshes[ *i* ] == NULL.
7503  *  \throw If the meshes do not share the node coordinates array.
7504  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7505  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7506  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7507  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7508  */
7509 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7510 {
7511   //All checks are delegated to MergeUMeshesOnSameCoords
7512   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7514   corr.resize(meshes.size());
7515   std::size_t nbOfMeshes=meshes.size();
7516   int offset=0;
7517   const int *o2nPtr=o2n->getConstPointer();
7518   for(std::size_t i=0;i<nbOfMeshes;i++)
7519     {
7520       DataArrayInt *tmp=DataArrayInt::New();
7521       int curNbOfCells=meshes[i]->getNumberOfCells();
7522       tmp->alloc(curNbOfCells,1);
7523       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7524       offset+=curNbOfCells;
7525       tmp->setName(meshes[i]->getName());
7526       corr[i]=tmp;
7527     }
7528   return ret.retn();
7529 }
7530
7531 /*!
7532  * Makes all given meshes share the nodal connectivity array. The common connectivity
7533  * array is created by concatenating the connectivity arrays of all given meshes. All
7534  * the given meshes must be of the same space dimension but dimension of cells **can
7535  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7536  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7537  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7538  *  \param [in,out] meshes - a vector of meshes to update.
7539  *  \throw If any of \a meshes is NULL.
7540  *  \throw If the coordinates array is not set in any of \a meshes.
7541  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7542  *  \throw If \a meshes are of different space dimension.
7543  */
7544 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7545 {
7546   std::size_t sz=meshes.size();
7547   if(sz==0 || sz==1)
7548     return;
7549   std::vector< const DataArrayDouble * > coords(meshes.size());
7550   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7551   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7552     {
7553       if((*it))
7554         {
7555           (*it)->checkConnectivityFullyDefined();
7556           const DataArrayDouble *coo=(*it)->getCoords();
7557           if(coo)
7558             *it2=coo;
7559           else
7560             {
7561               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7562               oss << " has no coordinate array defined !";
7563               throw INTERP_KERNEL::Exception(oss.str().c_str());
7564             }
7565         }
7566       else
7567         {
7568           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7569           oss << " is null !";
7570           throw INTERP_KERNEL::Exception(oss.str().c_str());
7571         }
7572     }
7573   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7574   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7575   int offset=(*it)->getNumberOfNodes();
7576   (*it++)->setCoords(res);
7577   for(;it!=meshes.end();it++)
7578     {
7579       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7580       (*it)->setCoords(res);
7581       (*it)->shiftNodeNumbersInConn(offset);
7582       offset+=oldNumberOfNodes;
7583     }
7584 }
7585
7586 /*!
7587  * Merges nodes coincident with a given precision within all given meshes that share
7588  * the nodal connectivity array. The given meshes **can be of different** mesh
7589  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7590  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7591  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7592  *  \param [in,out] meshes - a vector of meshes to update.
7593  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7594  *  \throw If any of \a meshes is NULL.
7595  *  \throw If the \a meshes do not share the same node coordinates array.
7596  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7597  */
7598 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7599 {
7600   if(meshes.empty())
7601     return ;
7602   std::set<const DataArrayDouble *> s;
7603   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7604     {
7605       if(*it)
7606         s.insert((*it)->getCoords());
7607       else
7608         {
7609           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 !";
7610           throw INTERP_KERNEL::Exception(oss.str().c_str());
7611         }
7612     }
7613   if(s.size()!=1)
7614     {
7615       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 !";
7616       throw INTERP_KERNEL::Exception(oss.str().c_str());
7617     }
7618   const DataArrayDouble *coo=*(s.begin());
7619   if(!coo)
7620     return;
7621   //
7622   DataArrayInt *comm,*commI;
7623   coo->findCommonTuples(eps,-1,comm,commI);
7624   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7625   int oldNbOfNodes=coo->getNumberOfTuples();
7626   int newNbOfNodes;
7627   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7628   if(oldNbOfNodes==newNbOfNodes)
7629     return ;
7630   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7631   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7632     {
7633       (*it)->renumberNodesInConn(o2n->getConstPointer());
7634       (*it)->setCoords(newCoords);
7635     } 
7636 }
7637
7638 /*!
7639  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [connBg,connEnd) and returns its extruded cell by inserting the result at the end of ret.
7640  * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7641  * @param isQuad specifies the policy of connectivity.
7642  * @ret in/out parameter in which the result will be append
7643  */
7644 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7645 {
7646   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7647   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7648   ret.push_back(cm.getExtrudedType());
7649   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7650   switch(flatType)
7651     {
7652     case INTERP_KERNEL::NORM_POINT1:
7653       {
7654         ret.push_back(connBg[1]);
7655         ret.push_back(connBg[1]+nbOfNodesPerLev);
7656         break;
7657       }
7658     case INTERP_KERNEL::NORM_SEG2:
7659       {
7660         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7661         ret.insert(ret.end(),conn,conn+4);
7662         break;
7663       }
7664     case INTERP_KERNEL::NORM_SEG3:
7665       {
7666         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7667         ret.insert(ret.end(),conn,conn+8);
7668         break;
7669       }
7670     case INTERP_KERNEL::NORM_QUAD4:
7671       {
7672         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7673         ret.insert(ret.end(),conn,conn+8);
7674         break;
7675       }
7676     case INTERP_KERNEL::NORM_TRI3:
7677       {
7678         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7679         ret.insert(ret.end(),conn,conn+6);
7680         break;
7681       }
7682     case INTERP_KERNEL::NORM_TRI6:
7683       {
7684         int conn[15]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4],connBg[5],connBg[6],connBg[4]+deltaz,connBg[5]+deltaz,connBg[6]+deltaz,
7685                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7686         ret.insert(ret.end(),conn,conn+15);
7687         break;
7688       }
7689     case INTERP_KERNEL::NORM_QUAD8:
7690       {
7691         int conn[20]={
7692           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7693           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7694           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7695         };
7696         ret.insert(ret.end(),conn,conn+20);
7697         break;
7698       }
7699     case INTERP_KERNEL::NORM_POLYGON:
7700       {
7701         std::back_insert_iterator< std::vector<int> > ii(ret);
7702         std::copy(connBg+1,connEnd,ii);
7703         *ii++=-1;
7704         std::reverse_iterator<const int *> rConnBg(connEnd);
7705         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7706         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7707         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7708         for(std::size_t i=0;i<nbOfRadFaces;i++)
7709           {
7710             *ii++=-1;
7711             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7712             std::copy(conn,conn+4,ii);
7713           }
7714         break;
7715       }
7716     default:
7717       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7718     }
7719 }
7720
7721 /*!
7722  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7723  */
7724 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7725 {
7726   double v[3]={0.,0.,0.};
7727   std::size_t sz=std::distance(begin,end);
7728   if(isQuadratic)
7729     sz/=2;
7730   for(std::size_t i=0;i<sz;i++)
7731     {
7732       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];
7733       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7734       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7735     }
7736   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7737 }
7738
7739 /*!
7740  * The polyhedron is specfied by its connectivity nodes in [begin,end).
7741  */
7742 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7743 {
7744   std::vector<std::pair<int,int> > edges;
7745   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7746   const int *bgFace=begin;
7747   for(std::size_t i=0;i<nbOfFaces;i++)
7748     {
7749       const int *endFace=std::find(bgFace+1,end,-1);
7750       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7751       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7752         {
7753           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7754           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7755             return false;
7756           edges.push_back(p1);
7757         }
7758       bgFace=endFace+1;
7759     }
7760   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7761 }
7762
7763 /*!
7764  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7765  */
7766 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7767 {
7768   double vec0[3],vec1[3];
7769   std::size_t sz=std::distance(begin,end);
7770   if(sz%2!=0)
7771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7772   int nbOfNodes=(int)sz/2;
7773   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7774   const double *pt0=coords+3*begin[0];
7775   const double *pt1=coords+3*begin[nbOfNodes];
7776   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7777   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7778 }
7779
7780 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7781 {
7782   std::size_t sz=std::distance(begin,end);
7783   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7784   std::size_t nbOfNodes(sz/2);
7785   std::copy(begin,end,(int *)tmp);
7786   for(std::size_t j=1;j<nbOfNodes;j++)
7787     {
7788       begin[j]=tmp[nbOfNodes-j];
7789       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7790     }
7791 }
7792
7793 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7794 {
7795   std::size_t sz=std::distance(begin,end);
7796   if(sz!=4)
7797     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7798   double vec0[3],vec1[3];
7799   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7800   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]; 
7801   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;
7802 }
7803
7804 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7805 {
7806   std::size_t sz=std::distance(begin,end);
7807   if(sz!=5)
7808     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7809   double vec0[3];
7810   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7811   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7812   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7813 }
7814
7815 /*!
7816  * 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) 
7817  * 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
7818  * a 2D space.
7819  *
7820  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7821  * \param [in] coords the coordinates with nb of components exactly equal to 3
7822  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7823  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7824  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7825  */
7826 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7827 {
7828   int nbFaces=std::count(begin+1,end,-1)+1;
7829   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7830   double *vPtr=v->getPointer();
7831   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7832   double *pPtr=p->getPointer();
7833   const int *stFaceConn=begin+1;
7834   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7835     {
7836       const int *endFaceConn=std::find(stFaceConn,end,-1);
7837       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7838       stFaceConn=endFaceConn+1;
7839     }
7840   pPtr=p->getPointer(); vPtr=v->getPointer();
7841   DataArrayInt *comm1=0,*commI1=0;
7842   v->findCommonTuples(eps,-1,comm1,commI1);
7843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7844   const int *comm1Ptr=comm1->getConstPointer();
7845   const int *commI1Ptr=commI1->getConstPointer();
7846   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7847   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7848   //
7849   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7850   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7851   mm->finishInsertingCells();
7852   //
7853   for(int i=0;i<nbOfGrps1;i++)
7854     {
7855       int vecId=comm1Ptr[commI1Ptr[i]];
7856       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7857       DataArrayInt *comm2=0,*commI2=0;
7858       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7859       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7860       const int *comm2Ptr=comm2->getConstPointer();
7861       const int *commI2Ptr=commI2->getConstPointer();
7862       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7863       for(int j=0;j<nbOfGrps2;j++)
7864         {
7865           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7866             {
7867               res->insertAtTheEnd(begin,end);
7868               res->pushBackSilent(-1);
7869             }
7870           else
7871             {
7872               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7873               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7874               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7875               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7876               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7877               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7878               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7879               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7880               const int *idsNodePtr=idsNode->getConstPointer();
7881               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];
7882               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7883               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7884               if(std::abs(norm)>eps)
7885                 {
7886                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7887                   mm3->rotate(center,vec,angle);
7888                 }
7889               mm3->changeSpaceDimension(2);
7890               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7891               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7892               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7893               int nbOfCells=mm4->getNumberOfCells();
7894               for(int k=0;k<nbOfCells;k++)
7895                 {
7896                   int l=0;
7897                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7898                     res->pushBackSilent(idsNodePtr[*work]);
7899                   res->pushBackSilent(-1);
7900                 }
7901             }
7902         }
7903     }
7904   res->popBackSilent();
7905 }
7906
7907 /*!
7908  * 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
7909  * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
7910  * 
7911  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7912  * \param [in] coords coordinates expected to have 3 components.
7913  * \param [in] begin start of the nodal connectivity of the face.
7914  * \param [in] end end of the nodal connectivity (excluded) of the face.
7915  * \param [out] v the normalized vector of size 3
7916  * \param [out] p the pos of plane
7917  */
7918 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7919 {
7920   std::size_t nbPoints=std::distance(begin,end);
7921   if(nbPoints<3)
7922     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7923   double vec[3];
7924   std::size_t j=0;
7925   bool refFound=false;
7926   for(;j<nbPoints-1 && !refFound;j++)
7927     {
7928       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7929       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7930       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7931       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7932       if(norm>eps)
7933         {
7934           refFound=true;
7935           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7936         }
7937     }
7938   for(std::size_t i=j;i<nbPoints-1;i++)
7939     {
7940       double curVec[3];
7941       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7942       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7943       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7944       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7945       if(norm<eps)
7946         continue;
7947       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7948       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];
7949       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7950       if(norm>eps)
7951         {
7952           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7953           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7954           return ;
7955         }
7956     }
7957   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7958 }
7959
7960 /*!
7961  * This method tries to obtain a well oriented polyhedron.
7962  * If the algorithm fails, an exception will be thrown.
7963  */
7964 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7965 {
7966   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7967   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7968   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7969   isPerm[0]=true;
7970   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7971   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7972   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7973   //
7974   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7975     {
7976       bgFace=begin;
7977       std::size_t smthChanged=0;
7978       for(std::size_t i=0;i<nbOfFaces;i++)
7979         {
7980           endFace=std::find(bgFace+1,end,-1);
7981           nbOfEdgesInFace=std::distance(bgFace,endFace);
7982           if(!isPerm[i])
7983             {
7984               bool b;
7985               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7986                 {
7987                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7988                   std::pair<int,int> p2(p1.second,p1.first);
7989                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7990                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7991                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7992                 }
7993               if(isPerm[i])
7994                 { 
7995                   if(!b)
7996                     std::reverse(bgFace+1,endFace);
7997                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7998                     {
7999                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8000                       std::pair<int,int> p2(p1.second,p1.first);
8001                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8002                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8003                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8004                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8005                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8006                       if(it!=edgesOK.end())
8007                         {
8008                           edgesOK.erase(it);
8009                           edgesFinished.push_back(p1);
8010                         }
8011                       else
8012                         edgesOK.push_back(p1);
8013                     }
8014                 }
8015             }
8016           bgFace=endFace+1;
8017         }
8018       if(smthChanged==0)
8019         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8020     }
8021   if(!edgesOK.empty())
8022     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8023   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8024     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8025       bgFace=begin;
8026       for(std::size_t i=0;i<nbOfFaces;i++)
8027         {
8028           endFace=std::find(bgFace+1,end,-1);
8029           std::reverse(bgFace+1,endFace);
8030           bgFace=endFace+1;
8031         }
8032     }
8033 }
8034
8035 /*!
8036  * This method makes the assumption spacedimension == meshdimension == 2.
8037  * This method works only for linear cells.
8038  * 
8039  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8040  */
8041 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8042 {
8043   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8044     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8045   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8046   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8047   int nbOfNodesExpected=m->getNumberOfNodes();
8048   if(m->getNumberOfCells()!=nbOfNodesExpected)
8049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8051   const int *n2oPtr=n2o->getConstPointer();
8052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8053   m->getReverseNodalConnectivity(revNodal,revNodalI);
8054   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8055   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8056   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8058   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8059   if(nbOfNodesExpected<1)
8060     return ret.retn();
8061   int prevCell=0;
8062   int prevNode=nodalPtr[nodalIPtr[0]+1];
8063   *work++=n2oPtr[prevNode];
8064   for(int i=1;i<nbOfNodesExpected;i++)
8065     {
8066       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8067         {
8068           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8069           conn.erase(prevNode);
8070           if(conn.size()==1)
8071             {
8072               int curNode=*(conn.begin());
8073               *work++=n2oPtr[curNode];
8074               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8075               shar.erase(prevCell);
8076               if(shar.size()==1)
8077                 {
8078                   prevCell=*(shar.begin());
8079                   prevNode=curNode;
8080                 }
8081               else
8082                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8083             }
8084           else
8085             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8086         }
8087       else
8088         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8089     }
8090   return ret.retn();
8091 }
8092
8093 /*!
8094  * This method makes the assumption spacedimension == meshdimension == 3.
8095  * This method works only for linear cells.
8096  * 
8097  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8098  */
8099 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8100 {
8101   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8103   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8104   const int *conn=m->getNodalConnectivity()->getConstPointer();
8105   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8106   int nbOfCells=m->getNumberOfCells();
8107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8108   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8109   if(nbOfCells<1)
8110     return ret.retn();
8111   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8112   for(int i=1;i<nbOfCells;i++)
8113     {
8114       *work++=-1;
8115       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8116     }
8117   return ret.retn();
8118 }
8119
8120 /*!
8121  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8122  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8123  */
8124 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8125 {
8126   double *w=zipFrmt;
8127   if(spaceDim==3)
8128     for(int i=0;i<nbOfNodesInCell;i++)
8129       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8130   else if(spaceDim==2)
8131     {
8132       for(int i=0;i<nbOfNodesInCell;i++)
8133         {
8134           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8135           *w++=0.;
8136         }
8137     }
8138   else
8139     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8140 }
8141
8142 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8143 {
8144   int nbOfCells=getNumberOfCells();
8145   if(nbOfCells<=0)
8146     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8147   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,-1,4};
8148   ofs << "  <" << getVTKDataSetType() << ">\n";
8149   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8150   ofs << "      <PointData>\n" << pointData << std::endl;
8151   ofs << "      </PointData>\n";
8152   ofs << "      <CellData>\n" << cellData << std::endl;
8153   ofs << "      </CellData>\n";
8154   ofs << "      <Points>\n";
8155   if(getSpaceDimension()==3)
8156     _coords->writeVTK(ofs,8,"Points");
8157   else
8158     {
8159       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8160       coo->writeVTK(ofs,8,"Points");
8161     }
8162   ofs << "      </Points>\n";
8163   ofs << "      <Cells>\n";
8164   const int *cPtr=_nodal_connec->getConstPointer();
8165   const int *cIPtr=_nodal_connec_index->getConstPointer();
8166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8167   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8168   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8170   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8171   int szFaceOffsets=0,szConn=0;
8172   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8173     {
8174       *w2=cPtr[cIPtr[i]];
8175       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8176         {
8177           *w1=-1;
8178           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8179           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8180         }
8181       else
8182         {
8183           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8184           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8185           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8186           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8187           w4=std::copy(c.begin(),c.end(),w4);
8188         }
8189     }
8190   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8191   types->writeVTK(ofs,8,"UInt8","types");
8192   offsets->writeVTK(ofs,8,"Int32","offsets");
8193   if(szFaceOffsets!=0)
8194     {//presence of Polyhedra
8195       connectivity->reAlloc(szConn);
8196       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8197       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8198       w1=faces->getPointer();
8199       for(int i=0;i<nbOfCells;i++)
8200         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8201           {
8202             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8203             *w1++=nbFaces;
8204             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8205             for(int j=0;j<nbFaces;j++)
8206               {
8207                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8208                 *w1++=(int)std::distance(w6,w5);
8209                 w1=std::copy(w6,w5,w1);
8210                 w6=w5+1;
8211               }
8212           }
8213       faces->writeVTK(ofs,8,"Int32","faces");
8214     }
8215   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8216   ofs << "      </Cells>\n";
8217   ofs << "    </Piece>\n";
8218   ofs << "  </" << getVTKDataSetType() << ">\n";
8219 }
8220
8221 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8222 {
8223   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8224   if(_mesh_dim==-2)
8225     { stream << " Not set !"; return ; }
8226   stream << " Mesh dimension : " << _mesh_dim << ".";
8227   if(_mesh_dim==-1)
8228     return ;
8229   if(!_coords)
8230     { stream << " No coordinates set !"; return ; }
8231   if(!_coords->isAllocated())
8232     { stream << " Coordinates set but not allocated !"; return ; }
8233   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8234   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8235   if(!_nodal_connec_index)
8236     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8237   if(!_nodal_connec_index->isAllocated())
8238     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8239   int lgth=_nodal_connec_index->getNumberOfTuples();
8240   int cpt=_nodal_connec_index->getNumberOfComponents();
8241   if(cpt!=1 || lgth<1)
8242     return ;
8243   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8244 }
8245
8246 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8247 {
8248   return std::string("UnstructuredGrid");
8249 }
8250
8251 /*!
8252  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8253  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8254  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8255  * meshes.
8256  *  \param [in] m1 - the first input mesh which is a partitioned object.
8257  *  \param [in] m2 - the second input mesh which is a partition tool.
8258  *  \param [in] eps - precision used to detect coincident mesh entities.
8259  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8260  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8261  *         this array using decrRef() as it is no more needed.
8262  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8263  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8264  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8265  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8266  *         it is no more needed.  
8267  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8268  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8269  *         is no more needed.  
8270  *  \throw If the coordinates array is not set in any of the meshes.
8271  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8272  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8273  */
8274 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8275 {
8276   m1->checkFullyDefined();
8277   m2->checkFullyDefined();
8278   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8280   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8281   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8282   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8283   std::vector<double> addCoo,addCoordsQuadratic;
8284   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8285   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8286   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8287                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8288   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8290   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8291   std::vector< std::vector<int> > intersectEdge2;
8292   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8293   subDiv2.clear(); dd5=0; dd6=0;
8294   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8295   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8296   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8297                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8298   //
8299   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8300   addCooDa->alloc((int)(addCoo.size())/2,2);
8301   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8302   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8303   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8304   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8305   std::vector<const DataArrayDouble *> coordss(4);
8306   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8307   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8308   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8313   ret->setConnectivity(conn,connI,true);
8314   ret->setCoords(coo);
8315   cellNb1=c1.retn(); cellNb2=c2.retn();
8316   return ret.retn();
8317 }
8318
8319 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8320                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8321                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8322                                                          const std::vector<double>& addCoords,
8323                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8324 {
8325   static const int SPACEDIM=2;
8326   std::vector<double> bbox1,bbox2;
8327   const double *coo1=m1->getCoords()->getConstPointer();
8328   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8329   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8330   int offset1=m1->getNumberOfNodes();
8331   const double *coo2=m2->getCoords()->getConstPointer();
8332   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8333   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8334   int offset2=offset1+m2->getNumberOfNodes();
8335   int offset3=offset2+((int)addCoords.size())/2;
8336   m1->getBoundingBoxForBBTree(bbox1);
8337   m2->getBoundingBoxForBBTree(bbox2);
8338   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8339   int ncell1=m1->getNumberOfCells();
8340   crI.push_back(0);
8341   for(int i=0;i<ncell1;i++)
8342     {
8343       std::vector<int> candidates2;
8344       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8345       std::map<INTERP_KERNEL::Node *,int> mapp;
8346       std::map<int,INTERP_KERNEL::Node *> mappRev;
8347       INTERP_KERNEL::QuadraticPolygon pol1;
8348       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8349       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8350       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8351       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8352                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8353       //
8354       std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result
8355       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8356       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8357       for(it1.first();!it1.finished();it1.next())
8358         edges1.insert(it1.current()->getPtr());
8359       //
8360       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8361       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8362       int ii=0;
8363       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8364         {
8365           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8366           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8367           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8368           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8369                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8370         }
8371       ii=0;
8372       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8373         {
8374           pol1.initLocationsWithOther(pol2s[ii]);
8375           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8376           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8377           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8378         }
8379       if(!edges1.empty())
8380         {
8381           try
8382             {
8383               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8384             }
8385           catch(INTERP_KERNEL::Exception& e)
8386             {
8387               std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
8388               throw INTERP_KERNEL::Exception(oss.str().c_str());
8389             }
8390         }
8391       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8392         (*it).second->decrRef();
8393     }
8394 }
8395
8396 /*!
8397  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8398  * 
8399  */
8400 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8401                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8402                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8403                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8404                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8405 {
8406   static const int SPACEDIM=2;
8407   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8408   desc2=DataArrayInt::New();
8409   descIndx2=DataArrayInt::New();
8410   revDesc2=DataArrayInt::New();
8411   revDescIndx2=DataArrayInt::New();
8412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8414   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8415   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8416   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8417   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8418   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8419   std::vector<double> bbox1,bbox2;
8420   m1Desc->getBoundingBoxForBBTree(bbox1);
8421   m2Desc->getBoundingBoxForBBTree(bbox2);
8422   int ncell1=m1Desc->getNumberOfCells();
8423   int ncell2=m2Desc->getNumberOfCells();
8424   intersectEdge1.resize(ncell1);
8425   colinear2.resize(ncell2);
8426   subDiv2.resize(ncell2);
8427   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8428   std::vector<int> candidates1(1);
8429   int offset1=m1->getNumberOfNodes();
8430   int offset2=offset1+m2->getNumberOfNodes();
8431   for(int i=0;i<ncell1;i++)
8432     {
8433       std::vector<int> candidates2;
8434       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8435       if(!candidates2.empty())
8436         {
8437           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8438           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8439           candidates1[0]=i;
8440           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8441           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8442           delete pol2;
8443           delete pol1;
8444         }
8445       else
8446         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8447     }
8448   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8449   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8450 }
8451
8452 /*!
8453  * This method performs the 2nd step of Partition of 2D mesh.
8454  * This method has 4 inputs :
8455  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8456  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8457  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8458  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8459  * @param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8460  * @param m2 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method.
8461  * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8462  */
8463 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8464 {
8465   int offset1=m1->getNumberOfNodes();
8466   int ncell=m2->getNumberOfCells();
8467   const int *c=m2->getNodalConnectivity()->getConstPointer();
8468   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8469   const double *coo=m2->getCoords()->getConstPointer();
8470   const double *cooBis=m1->getCoords()->getConstPointer();
8471   int offset2=offset1+m2->getNumberOfNodes();
8472   intersectEdge.resize(ncell);
8473   for(int i=0;i<ncell;i++,cI++)
8474     {
8475       const std::vector<int>& divs=subDiv[i];
8476       int nnode=cI[1]-cI[0]-1;
8477       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8478       std::map<INTERP_KERNEL::Node *, int> mapp22;
8479       for(int j=0;j<nnode;j++)
8480         {
8481           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8482           int nnid=c[(*cI)+j+1];
8483           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8484           mapp22[nn]=nnid+offset1;
8485         }
8486       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8487       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8488         ((*it).second.first)->decrRef();
8489       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8490       std::map<INTERP_KERNEL::Node *,int> mapp3;
8491       for(std::size_t j=0;j<divs.size();j++)
8492         {
8493           int id=divs[j];
8494           INTERP_KERNEL::Node *tmp=0;
8495           if(id<offset1)
8496             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8497           else if(id<offset2)
8498             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8499           else
8500             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8501           addNodes[j]=tmp;
8502           mapp3[tmp]=id;
8503         }
8504       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8505       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8506         (*it)->decrRef();
8507       e->decrRef();
8508     }
8509 }
8510
8511 /*!
8512  * This method is part of the Slice3D algorithm. It is the first step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8513  * This method allows to compute given the status of 3D curve cells and the descending connectivity 3DSurf->3DCurve to deduce the intersection of each 3D surf cells
8514  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8515  * @param cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8516  * @param nodesOnPlane, returns all the nodes that are on the plane.
8517  * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
8518  * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8519  * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
8520  * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8521  * @param desc is the descending connectivity 3DSurf->3DCurve
8522  * @param descIndx is the descending connectivity index 3DSurf->3DCurve
8523  * @param cut3DSuf input/output param.
8524  */
8525 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8526                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8527                                                    const int *desc, const int *descIndx, 
8528                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8529 {
8530   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8531   int nbOf3DSurfCell=(int)cut3DSurf.size();
8532   for(int i=0;i<nbOf3DSurfCell;i++)
8533     {
8534       std::vector<int> res;
8535       int offset=descIndx[i];
8536       int nbOfSeg=descIndx[i+1]-offset;
8537       for(int j=0;j<nbOfSeg;j++)
8538         {
8539           int edgeId=desc[offset+j];
8540           int status=cut3DCurve[edgeId];
8541           if(status!=-2)
8542             {
8543               if(status>-1)
8544                 res.push_back(status);
8545               else
8546                 {
8547                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8548                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8549                 }
8550             }
8551         }
8552       switch(res.size())
8553         {
8554         case 2:
8555           {
8556             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8557             break;
8558           }
8559         case 1:
8560         case 0:
8561           {
8562             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8563             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8564             if(res.size()==2)
8565               {
8566                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8567               }
8568             else
8569               {
8570                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8571               }
8572             break;
8573           }
8574         default:
8575           {// case when plane is on a multi colinear edge of a polyhedron
8576             if((int)res.size()==2*nbOfSeg)
8577               {
8578                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8579               }
8580             else
8581               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8582           }
8583         }
8584     }
8585 }
8586
8587 /*!
8588  * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8589  * This method is part of the Slice3D algorithm. It is the second step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8590  * This method allows to compute given the result of 3D surf cells with plane and the descending connectivity 3D->3DSurf to deduce the intersection of each 3D cells
8591  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8592  * @param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8593  * @param desc is the descending connectivity 3D->3DSurf
8594  * @param descIndx is the descending connectivity index 3D->3DSurf
8595  */
8596 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8597                                                   const int *desc, const int *descIndx,
8598                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8599 {
8600   checkFullyDefined();
8601   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8602     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8603   const int *nodal3D=_nodal_connec->getConstPointer();
8604   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8605   int nbOfCells=getNumberOfCells();
8606   for(int i=0;i<nbOfCells;i++)
8607     {
8608       std::map<int, std::set<int> > m;
8609       int offset=descIndx[i];
8610       int nbOfFaces=descIndx[i+1]-offset;
8611       int start=-1;
8612       int end=-1;
8613       for(int j=0;j<nbOfFaces;j++)
8614         {
8615           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8616           if(p.first!=-1 && p.second!=-1)
8617             {
8618               if(p.first!=-2)
8619                 {
8620                   start=p.first; end=p.second;
8621                   m[p.first].insert(p.second);
8622                   m[p.second].insert(p.first);
8623                 }
8624               else
8625                 {
8626                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8627                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8628                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8629                   INTERP_KERNEL::NormalizedCellType cmsId;
8630                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8631                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8632                   for(unsigned k=0;k<nbOfNodesSon;k++)
8633                     {
8634                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8635                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8636                     }
8637                 }
8638             }
8639         }
8640       if(m.empty())
8641         continue;
8642       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8643       int prev=end;
8644       while(end!=start)
8645         {
8646           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8647           const std::set<int>& s=(*it).second;
8648           std::set<int> s2; s2.insert(prev);
8649           std::set<int> s3;
8650           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8651           if(s3.size()==1)
8652             {
8653               int val=*s3.begin();
8654               conn.push_back(start);
8655               prev=start;
8656               start=val;
8657             }
8658           else
8659             start=end;
8660         }
8661       conn.push_back(end);
8662       if(conn.size()>3)
8663         {
8664           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8665           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8666           cellIds->pushBackSilent(i);
8667         }
8668     }
8669 }
8670
8671 /*!
8672  * 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
8673  * 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
8674  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8675  * 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
8676  * 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.
8677  * 
8678  * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8679  */
8680 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8681 {
8682   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8683   if(sz>=4)
8684     {
8685       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8686       if(cm.getDimension()==2)
8687         {
8688           const int *node=nodalConnBg+1;
8689           int startNode=*node++;
8690           double refX=coords[2*startNode];
8691           for(;node!=nodalConnEnd;node++)
8692             {
8693               if(coords[2*(*node)]<refX)
8694                 {
8695                   startNode=*node;
8696                   refX=coords[2*startNode];
8697                 }
8698             }
8699           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8700           refX=1e300;
8701           double tmp1;
8702           double tmp2[2];
8703           double angle0=-M_PI/2;
8704           //
8705           int nextNode=-1;
8706           int prevNode=-1;
8707           double resRef;
8708           double angleNext;
8709           while(nextNode!=startNode)
8710             {
8711               nextNode=-1;
8712               resRef=1e300;
8713               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8714                 {
8715                   if(*node!=tmpOut.back() && *node!=prevNode)
8716                     {
8717                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8718                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8719                       double res;
8720                       if(angleM<=angle0)
8721                         res=angle0-angleM;
8722                       else
8723                         res=angle0-angleM+2.*M_PI;
8724                       if(res<resRef)
8725                         {
8726                           nextNode=*node;
8727                           resRef=res;
8728                           angleNext=angleM;
8729                         }
8730                     }
8731                 }
8732               if(nextNode!=startNode)
8733                 {
8734                   angle0=angleNext-M_PI;
8735                   if(angle0<-M_PI)
8736                     angle0+=2*M_PI;
8737                   prevNode=tmpOut.back();
8738                   tmpOut.push_back(nextNode);
8739                 }
8740             }
8741           std::vector<int> tmp3(2*(sz-1));
8742           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8743           std::copy(nodalConnBg+1,nodalConnEnd,it);
8744           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8745             {
8746               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8747               return false;
8748             }
8749           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8750             {
8751               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8752               return false;
8753             }
8754           else
8755             {
8756               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8757               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8758               return true;
8759             }
8760         }
8761       else
8762         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8763     }
8764   else
8765     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8766 }
8767
8768 /*!
8769  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8770  * 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.
8771  * 
8772  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8773  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8774  * \param [in,out] arr array in which the remove operation will be done.
8775  * \param [in,out] arrIndx array in the remove operation will modify
8776  * \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])
8777  * \return true if \b arr and \b arrIndx have been modified, false if not.
8778  */
8779 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8780 {
8781   if(!arrIndx || !arr)
8782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8783   if(offsetForRemoval<0)
8784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8785   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8786   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8787   int *arrIPtr=arrIndx->getPointer();
8788   *arrIPtr++=0;
8789   int previousArrI=0;
8790   const int *arrPtr=arr->getConstPointer();
8791   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8792   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8793     {
8794       if(*arrIPtr-previousArrI>offsetForRemoval)
8795         {
8796           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8797             {
8798               if(s.find(*work)==s.end())
8799                 arrOut.push_back(*work);
8800             }
8801         }
8802       previousArrI=*arrIPtr;
8803       *arrIPtr=(int)arrOut.size();
8804     }
8805   if(arr->getNumberOfTuples()==(int)arrOut.size())
8806     return false;
8807   arr->alloc((int)arrOut.size(),1);
8808   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8809   return true;
8810 }
8811
8812 /*!
8813  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8814  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8815  * The selection of extraction is done standardly in new2old format.
8816  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8817  *
8818  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8819  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8820  * \param [in] arrIn arr origin array from which the extraction will be done.
8821  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8822  * \param [out] arrOut the resulting array
8823  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8824  */
8825 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8826                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8827 {
8828   if(!arrIn || !arrIndxIn)
8829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8830   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8831   const int *arrInPtr=arrIn->getConstPointer();
8832   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8833   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8834   int maxSizeOfArr=arrIn->getNumberOfTuples();
8835   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8837   arrIo->alloc((int)(sz+1),1);
8838   const int *idsIt=idsOfSelectBg;
8839   int *work=arrIo->getPointer();
8840   *work++=0;
8841   int lgth=0;
8842   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8843     {
8844       if(*idsIt>=0 && *idsIt<nbOfGrps)
8845         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8846       else
8847         {
8848           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8849           throw INTERP_KERNEL::Exception(oss.str().c_str());
8850         }
8851       if(lgth>=work[-1])
8852         *work=lgth;
8853       else
8854         {
8855           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8856           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8857           throw INTERP_KERNEL::Exception(oss.str().c_str());
8858         }
8859     }
8860   arro->alloc(lgth,1);
8861   work=arro->getPointer();
8862   idsIt=idsOfSelectBg;
8863   for(std::size_t i=0;i<sz;i++,idsIt++)
8864     {
8865       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8866         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8867       else
8868         {
8869           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8870           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8871           throw INTERP_KERNEL::Exception(oss.str().c_str());
8872         }
8873     }
8874   arrOut=arro.retn();
8875   arrIndexOut=arrIo.retn();
8876 }
8877
8878 /*!
8879  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8880  * 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
8881  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8882  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8883  *
8884  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8885  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8886  * \param [in] arrIn arr origin array from which the extraction will be done.
8887  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8888  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8889  * \param [in] srcArrIndex index array of \b srcArr
8890  * \param [out] arrOut the resulting array
8891  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8892  * 
8893  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8894  */
8895 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8896                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8897                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8898 {
8899   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8900     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8903   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8904   std::vector<bool> v(nbOfTuples,true);
8905   int offset=0;
8906   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8907   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8908   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8909     {
8910       if(*it>=0 && *it<nbOfTuples)
8911         {
8912           v[*it]=false;
8913           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8914         }
8915       else
8916         {
8917           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8918           throw INTERP_KERNEL::Exception(oss.str().c_str());
8919         }
8920     }
8921   srcArrIndexPtr=srcArrIndex->getConstPointer();
8922   arrIo->alloc(nbOfTuples+1,1);
8923   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8924   const int *arrInPtr=arrIn->getConstPointer();
8925   const int *srcArrPtr=srcArr->getConstPointer();
8926   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8927   int *arroPtr=arro->getPointer();
8928   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8929     {
8930       if(v[ii])
8931         {
8932           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8933           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8934         }
8935       else
8936         {
8937           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8938           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8939           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8940         }
8941     }
8942   arrOut=arro.retn();
8943   arrIndexOut=arrIo.retn();
8944 }
8945
8946 /*!
8947  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8948  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8949  *
8950  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8951  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8952  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8953  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8954  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8955  * \param [in] srcArrIndex index array of \b srcArr
8956  * 
8957  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8958  */
8959 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8960                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8961 {
8962   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8964   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8965   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8966   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8967   int *arrInOutPtr=arrInOut->getPointer();
8968   const int *srcArrPtr=srcArr->getConstPointer();
8969   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8970     {
8971       if(*it>=0 && *it<nbOfTuples)
8972         {
8973           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8974             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8975           else
8976             {
8977               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] !";
8978               throw INTERP_KERNEL::Exception(oss.str().c_str());
8979             }
8980         }
8981       else
8982         {
8983           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8984           throw INTERP_KERNEL::Exception(oss.str().c_str());
8985         }
8986     }
8987 }
8988
8989 /*!
8990  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8991  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8992  * 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]].
8993  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8994  * A negative value in \b arrIn means that it is ignored.
8995  * 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.
8996  * 
8997  * \param [in] arrIn arr origin array from which the extraction will be done.
8998  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8999  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9000  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9001  */
9002 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9003 {
9004   int seed=0,nbOfDepthPeelingPerformed=0;
9005   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9006 }
9007
9008 /*!
9009  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9010  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9011  * 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]].
9012  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9013  * A negative value in \b arrIn means that it is ignored.
9014  * 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.
9015  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9016  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9017  * \param [in] arrIn arr origin array from which the extraction will be done.
9018  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9019  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9020  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9021  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9022  * \sa MEDCouplingUMesh::partitionBySpreadZone
9023  */
9024 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9025 {
9026   nbOfDepthPeelingPerformed=0;
9027   if(!arrIndxIn)
9028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9029   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9030   if(nbOfTuples<=0)
9031     {
9032       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9033       return ret;
9034     }
9035   //
9036   std::vector<bool> fetched(nbOfTuples,false);
9037   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9038 }
9039
9040 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9041 {
9042   nbOfDepthPeelingPerformed=0;
9043   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9044     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9045   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9046   std::vector<bool> fetched2(nbOfTuples,false);
9047   int i=0;
9048   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9049     {
9050       if(*seedElt>=0 && *seedElt<nbOfTuples)
9051         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9052       else
9053         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
9054     }
9055   const int *arrInPtr=arrIn->getConstPointer();
9056   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9057   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9058   std::vector<int> idsToFetch1(seedBg,seedEnd);
9059   std::vector<int> idsToFetch2;
9060   std::vector<int> *idsToFetch=&idsToFetch1;
9061   std::vector<int> *idsToFetchOther=&idsToFetch2;
9062   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9063     {
9064       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9065         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9066           if(!fetched[*it2])
9067             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9068       std::swap(idsToFetch,idsToFetchOther);
9069       idsToFetchOther->clear();
9070       nbOfDepthPeelingPerformed++;
9071     }
9072   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9073   i=0;
9074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9075   int *retPtr=ret->getPointer();
9076   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9077     if(*it)
9078       *retPtr++=i;
9079   return ret.retn();
9080 }
9081
9082 /*!
9083  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9084  * 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
9085  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9086  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9087  *
9088  * \param [in] start begin of set of ids of the input extraction (included)
9089  * \param [in] end end of set of ids of the input extraction (excluded)
9090  * \param [in] step step of the set of ids in range mode.
9091  * \param [in] arrIn arr origin array from which the extraction will be done.
9092  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9093  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9094  * \param [in] srcArrIndex index array of \b srcArr
9095  * \param [out] arrOut the resulting array
9096  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9097  * 
9098  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9099  */
9100 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9101                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9102                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9103 {
9104   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9105     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9108   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9109   int offset=0;
9110   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9111   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9112   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9113   int it=start;
9114   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9115     {
9116       if(it>=0 && it<nbOfTuples)
9117         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9118       else
9119         {
9120           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9121           throw INTERP_KERNEL::Exception(oss.str().c_str());
9122         }
9123     }
9124   srcArrIndexPtr=srcArrIndex->getConstPointer();
9125   arrIo->alloc(nbOfTuples+1,1);
9126   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9127   const int *arrInPtr=arrIn->getConstPointer();
9128   const int *srcArrPtr=srcArr->getConstPointer();
9129   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9130   int *arroPtr=arro->getPointer();
9131   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9132     {
9133       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9134       if(pos<0)
9135         {
9136           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9137           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9138         }
9139       else
9140         {
9141           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9142           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9143         }
9144     }
9145   arrOut=arro.retn();
9146   arrIndexOut=arrIo.retn();
9147 }
9148
9149 /*!
9150  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9151  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9152  *
9153  * \param [in] start begin of set of ids of the input extraction (included)
9154  * \param [in] end end of set of ids of the input extraction (excluded)
9155  * \param [in] step step of the set of ids in range mode.
9156  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9157  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9158  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9159  * \param [in] srcArrIndex index array of \b srcArr
9160  * 
9161  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9162  */
9163 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9164                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9165 {
9166   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9168   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9169   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9170   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9171   int *arrInOutPtr=arrInOut->getPointer();
9172   const int *srcArrPtr=srcArr->getConstPointer();
9173   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9174   int it=start;
9175   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9176     {
9177       if(it>=0 && it<nbOfTuples)
9178         {
9179           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9180             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9181           else
9182             {
9183               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9184               throw INTERP_KERNEL::Exception(oss.str().c_str());
9185             }
9186         }
9187       else
9188         {
9189           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9190           throw INTERP_KERNEL::Exception(oss.str().c_str());
9191         }
9192     }
9193 }
9194
9195 /*!
9196  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9197  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9198  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9199  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9200  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9201  * 
9202  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9203  */
9204 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9205 {
9206   checkFullyDefined();
9207   int mdim=getMeshDimension();
9208   int spaceDim=getSpaceDimension();
9209   if(mdim!=spaceDim)
9210     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9211   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9212   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9213   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9214   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9215   ret->setCoords(getCoords());
9216   ret->allocateCells((int)partition.size());
9217   //
9218   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9219     {
9220       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9221       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9222       switch(mdim)
9223         {
9224         case 2:
9225           cell=tmp->buildUnionOf2DMesh();
9226           break;
9227         case 3:
9228           cell=tmp->buildUnionOf3DMesh();
9229           break;
9230         default:
9231           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9232         }
9233       
9234       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9235     }
9236   //
9237   ret->finishInsertingCells();
9238   return ret.retn();
9239 }
9240
9241 /*!
9242  * This method partitions \b this into contiguous zone.
9243  * This method only needs a well defined connectivity. Coordinates are not considered here.
9244  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9245  */
9246 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9247 {
9248   //#if 0
9249   int nbOfCellsCur=getNumberOfCells();
9250   std::vector<DataArrayInt *> ret;
9251   if(nbOfCellsCur<=0)
9252     return ret;
9253   DataArrayInt *neigh=0,*neighI=0;
9254   computeNeighborsOfCells(neigh,neighI);
9255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9256   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9257   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9258   int seed=0;
9259   while(seed<nbOfCellsCur)
9260     {
9261       int nbOfPeelPerformed=0;
9262       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9263       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9264     }
9265   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9266     ret.push_back((*it).retn());
9267   return ret;
9268   //#endif
9269 #if 0
9270   int nbOfCellsCur=getNumberOfCells();
9271   DataArrayInt *neigh=0,*neighI=0;
9272   computeNeighborsOfCells(neigh,neighI);
9273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9275   std::vector<DataArrayInt *> ret;
9276   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9277   while(nbOfCellsCur>0)
9278     {
9279       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9280       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9281       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9282       ret2.push_back(tmp2);  ret.push_back(tmp2);
9283       nbOfCellsCur=tmp3->getNumberOfTuples();
9284       if(nbOfCellsCur>0)
9285         {
9286           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9287           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9288           neighAuto=neigh;
9289           neighIAuto=neighI;
9290           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9291           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9292         }
9293     }
9294   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9295     (*it)->incrRef();
9296   return ret;
9297 #endif
9298 }
9299
9300 /*!
9301  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9302  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9303  *
9304  * \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.
9305  * \return a newly allocated DataArrayInt to be managed by the caller.
9306  * \throw In case of \a code has not the right format (typically of size 3*n)
9307  */
9308 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9309 {
9310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9311   std::size_t nb=code.size()/3;
9312   if(code.size()%3!=0)
9313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9314   ret->alloc((int)nb,2);
9315   int *retPtr=ret->getPointer();
9316   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9317     {
9318       retPtr[0]=code[3*i+2];
9319       retPtr[1]=code[3*i+2]+code[3*i+1];
9320     }
9321   return ret.retn();
9322 }
9323
9324 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9325                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9326 {
9327   if(mesh)
9328     {
9329       mesh->incrRef();
9330       _nb_cell=mesh->getNumberOfCells();
9331     }
9332 }
9333
9334 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9335 {
9336   if(_mesh)
9337     _mesh->decrRef();
9338   if(_own_cell)
9339     delete _cell;
9340 }
9341
9342 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9343                                                                                                                                _own_cell(false),_cell_id(bg-1),
9344                                                                                                                                _nb_cell(end)
9345 {
9346   if(mesh)
9347     mesh->incrRef();
9348 }
9349
9350 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9351 {
9352   _cell_id++;
9353   if(_cell_id<_nb_cell)
9354     {
9355       _cell->next();
9356       return _cell;
9357     }
9358   else
9359     return 0;
9360 }
9361
9362 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9363 {
9364   if(_mesh)
9365     _mesh->incrRef();
9366 }
9367
9368 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9369 {
9370   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9371 }
9372
9373 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9374 {
9375   if(_mesh)
9376     _mesh->decrRef();
9377 }
9378
9379 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9380                                                                                                                                                                   _itc(itc),
9381                                                                                                                                                                   _bg(bg),_end(end)
9382 {
9383   if(_mesh)
9384     _mesh->incrRef();
9385 }
9386
9387 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9388 {
9389   if(_mesh)
9390     _mesh->decrRef();
9391 }
9392
9393 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9394 {
9395   return _type;
9396 }
9397
9398 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9399 {
9400   return _end-_bg;
9401 }
9402
9403 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9404 {
9405   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9406 }
9407
9408 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9409 {
9410   if(mesh)
9411     {
9412       mesh->incrRef();
9413       _nb_cell=mesh->getNumberOfCells();
9414     }
9415 }
9416
9417 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9418 {
9419   if(_mesh)
9420     _mesh->decrRef();
9421   delete _cell;
9422 }
9423
9424 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9425 {
9426   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9427   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9428   if(_cell_id<_nb_cell)
9429     {
9430       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9431       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9432       int startId=_cell_id;
9433       _cell_id+=nbOfElems;
9434       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9435     }
9436   else
9437     return 0;
9438 }
9439
9440 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9441 {
9442   if(mesh)
9443     {
9444       _conn=mesh->getNodalConnectivity()->getPointer();
9445       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9446     }
9447 }
9448
9449 void MEDCouplingUMeshCell::next()
9450 {
9451   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9452     {
9453       _conn+=_conn_lgth;
9454       _conn_indx++;
9455     }
9456   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9457 }
9458
9459 std::string MEDCouplingUMeshCell::repr() const
9460 {
9461   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9462     {
9463       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9464       oss << " : ";
9465       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9466       return oss.str();
9467     }
9468   else
9469     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9470 }
9471
9472 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9473 {
9474   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9475     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9476   else
9477     return INTERP_KERNEL::NORM_ERROR;
9478 }
9479
9480 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9481 {
9482   lgth=_conn_lgth;
9483   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9484     return _conn;
9485   else
9486     return 0;
9487 }