Salome HOME
Merge from V6_main 12/04/2013
[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  * \brief 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 maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
524   pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
525   if(pt!=da->getConstPointer()+da->getNbOfElems())
526     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
527   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
528   nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
529   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
530 }
531
532 /*!
533  * Checks if \a this and \a other meshes are geometrically equivalent, else an
534  * exception is thrown. The meshes are considered equivalent if (1) they share one
535  * node coordinates array and (2) they contain the same cells (with use of a specified
536  * cell comparison technique). The mapping from cells of the \a other to ones of \a this 
537  * is returned via an out parameter.
538  *  \param [in] other - the mesh to compare with.
539  *  \param [in] cellCompPol - id [0-2] of cell comparison method. See the meaning of
540  *         each method in description of MEDCouplingUMesh::zipConnectivityTraducer().
541  *  \param [in] prec - a not used parameter.
542  *  \param [out] cellCor - the permutation array in "Old to New" mode. The caller is
543  *         to delete this array using decrRef() as it is no more needed.
544  *  \throw If the two meshes do not match.
545  *
546  * \ref cpp_mcumesh_checkDeepEquivalWith "Here is a C++ example".<br>
547  * \ref  py_mcumesh_checkDeepEquivalWith "Here is a Python example".
548  */
549 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
550                                                        DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
551 {
552   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
553   if(!otherC)
554     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
555   MEDCouplingMesh::checkFastEquivalWith(other,prec);
556   if(_types!=otherC->_types)
557     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
558   if(_coords!=otherC->_coords)
559     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
560   std::vector<const MEDCouplingUMesh *> ms(2);
561   ms[0]=this;
562   ms[1]=otherC;
563   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
565   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
566   const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
567   if(pt!=da->getConstPointer()+da->getNbOfElems())
568     {
569       throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
570     }
571   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
572   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
573 }
574
575 /*!
576  * Checks if \a this and \a other meshes are geometrically equivalent with high
577  * probability, else an exception is thrown. The meshes are considered equivalent if
578  * (1) meshes contain the same number of nodes and the same number of elements of the
579  * same types (2) three cells of the two meshes are based on coincident nodes (with a
580  * specified precision).
581  *  \param [in] other - the mesh to compare with.
582  *  \param [in] prec - the precision used to compare nodes of the two meshes.
583  *  \throw If the two meshes do not match.
584  */
585 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
586 {
587   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
588   if(!otherC)
589     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
590   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
591   int nbOfCells=getNumberOfCells();
592   if(nbOfCells<1)
593     return ;
594   bool status=true;
595   status&=areCellsFrom2MeshEqual(otherC,0,prec);
596   status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
597   status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
598   if(!status)
599     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
600 }
601
602 /*!
603  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
604  * cells each node belongs to.
605  * \warning For speed reasons, this method does not check if node ids in the nodal
606  *          connectivity correspond to the size of node coordinates array.
607  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
608  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
609  *        dividing cell ids in \a revNodal into groups each referring to one
610  *        node. Its every element (except the last one) is an index pointing to the
611  *         first id of a group of cells. For example cells sharing the node #1 are 
612  *        described by following range of indices: 
613  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
614  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
615  *        Number of cells sharing the *i*-th node is
616  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
617  * \throw If the coordinates array is not set.
618  * \throw If the nodal connectivity of cells is not defined.
619  * 
620  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
621  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
622  */
623 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
624 {
625   checkFullyDefined();
626   int nbOfNodes=getNumberOfNodes();
627   int *revNodalIndxPtr=new int[nbOfNodes+1];
628   revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
629   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
630   const int *conn=_nodal_connec->getConstPointer();
631   const int *connIndex=_nodal_connec_index->getConstPointer();
632   int nbOfCells=getNumberOfCells();
633   int nbOfEltsInRevNodal=0;
634   for(int eltId=0;eltId<nbOfCells;eltId++)
635     {
636       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
637       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
638       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
639         if(*iter>=0)//for polyhedrons
640           {
641             nbOfEltsInRevNodal++;
642             revNodalIndxPtr[(*iter)+1]++;
643           }
644     }
645   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
646   int *revNodalPtr=new int[nbOfEltsInRevNodal];
647   revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
648   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
649   for(int eltId=0;eltId<nbOfCells;eltId++)
650     {
651       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
652       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
653       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
654         if(*iter>=0)//for polyhedrons
655           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
656     }
657 }
658
659 /// @cond INTERNAL
660
661 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
662 {
663   return id;
664 }
665
666 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
667 {
668   if(!compute)
669     return id+1;
670   else
671     {
672       if(cm.getOrientationStatus(nb,conn1,conn2))
673         return id+1;
674       else
675         return -(id+1);
676     }
677 }
678
679 class MinusOneSonsGenerator
680 {
681 public:
682   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
683   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
684   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
685   static const int DELTA=1;
686 private:
687   const INTERP_KERNEL::CellModel& _cm;
688 };
689
690 class MinusOneSonsGeneratorBiQuadratic
691 {
692 public:
693   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
694   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
695   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
696   static const int DELTA=1;
697 private:
698   const INTERP_KERNEL::CellModel& _cm;
699 };
700
701 class MinusTwoSonsGenerator
702 {
703 public:
704   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
705   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
706   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
707   static const int DELTA=2;
708 private:
709   const INTERP_KERNEL::CellModel& _cm;
710 };
711
712 /// @endcond
713
714 /*!
715  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
716  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
717  * describing correspondence between cells of \a this and the result meshes are
718  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
719  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
720  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
721  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
722  * \warning For speed reasons, this method does not check if node ids in the nodal
723  *          connectivity correspond to the size of node coordinates array.
724  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
725  *          to write this mesh to the MED file, its cells must be sorted using
726  *          sortCellsInMEDFileFrmt().
727  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
728  *         each cell of \a this mesh.
729  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
730  *        dividing cell ids in \a desc into groups each referring to one
731  *        cell of \a this mesh. Its every element (except the last one) is an index
732  *        pointing to the first id of a group of cells. For example cells of the
733  *        result mesh bounding the cell #1 of \a this mesh are described by following
734  *        range of indices:
735  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
736  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
737  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
738  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
739  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
740  *         by each cell of the result mesh.
741  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
742  *        in the result mesh,
743  *        dividing cell ids in \a revDesc into groups each referring to one
744  *        cell of the result mesh the same way as \a descIndx divides \a desc.
745  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
746  *        delete this mesh using decrRef() as it is no more needed.
747  *  \throw If the coordinates array is not set.
748  *  \throw If the nodal connectivity of cells is node defined.
749  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
750  *         revDescIndx == NULL.
751  * 
752  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
753  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
754  * \sa buildDescendingConnectivity2()
755  */
756 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
757 {
758   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
759 }
760
761 /*!
762  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
763  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
764  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
765  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
766  * \sa MEDCouplingUMesh::buildDescendingConnectivity
767  */
768 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
769 {
770   checkFullyDefined();
771   if(getMeshDimension()!=3)
772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
773   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
774 }
775
776 /*!
777  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
778  * this->getMeshDimension(), that bound cells of \a this mesh. In
779  * addition arrays describing correspondence between cells of \a this and the result
780  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
781  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
782  *  mesh. This method differs from buildDescendingConnectivity() in that apart
783  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
784  * result meshes. So a positive id means that order of nodes in corresponding cells
785  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
786  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
787  * i.e. cell ids are one-based.
788  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
789  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
790  * \warning For speed reasons, this method does not check if node ids in the nodal
791  *          connectivity correspond to the size of node coordinates array.
792  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
793  *          to write this mesh to the MED file, its cells must be sorted using
794  *          sortCellsInMEDFileFrmt().
795  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
796  *         each cell of \a this mesh.
797  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
798  *        dividing cell ids in \a desc into groups each referring to one
799  *        cell of \a this mesh. Its every element (except the last one) is an index
800  *        pointing to the first id of a group of cells. For example cells of the
801  *        result mesh bounding the cell #1 of \a this mesh are described by following
802  *        range of indices:
803  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
804  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
805  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
806  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
807  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
808  *         by each cell of the result mesh.
809  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
810  *        in the result mesh,
811  *        dividing cell ids in \a revDesc into groups each referring to one
812  *        cell of the result mesh the same way as \a descIndx divides \a desc.
813  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
814  *        shares the node coordinates array with \a this mesh. The caller is to
815  *        delete this mesh using decrRef() as it is no more needed.
816  *  \throw If the coordinates array is not set.
817  *  \throw If the nodal connectivity of cells is node defined.
818  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
819  *         revDescIndx == NULL.
820  * 
821  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
822  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
823  * \sa buildDescendingConnectivity()
824  */
825 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
826 {
827   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
828 }
829
830 /*!
831  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
832  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
833  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
834  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
835  *
836  * \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
837  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
838  * \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.
839  */
840 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
841 {
842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
846   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
847   meshDM1=0;
848   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
849 }
850
851 /*!
852  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
853  * 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,
854  * excluding a set of meshdim-1 cells in input descending connectivity.
855  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
856  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
857  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
858  *
859  * \param [in] desc descending connectivity array.
860  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
861  * \param [in] revDesc reverse descending connectivity array.
862  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
863  * \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
864  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
865  * \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.
866  */
867 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
868                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
869 {
870   if(!desc || !descIndx || !revDesc || !revDescIndx)
871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
872   const int *descPtr=desc->getConstPointer();
873   const int *descIPtr=descIndx->getConstPointer();
874   const int *revDescPtr=revDesc->getConstPointer();
875   const int *revDescIPtr=revDescIndx->getConstPointer();
876   //
877   int nbCells=descIndx->getNumberOfTuples()-1;
878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
880   int *out1Ptr=out1->getPointer();
881   *out1Ptr++=0;
882   out0->reserve(desc->getNumberOfTuples());
883   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
884     {
885       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
886         {
887           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
888           s.erase(i);
889           out0->insertAtTheEnd(s.begin(),s.end());
890         }
891       *out1Ptr=out0->getNumberOfTuples();
892     }
893   neighbors=out0.retn();
894   neighborsIndx=out1.retn();
895 }
896
897 /// @cond INTERNAL
898
899 /*!
900  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
901  * For speed reasons no check of this will be done.
902  */
903 template<class SonsGenerator>
904 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
905 {
906   if(!desc || !descIndx || !revDesc || !revDescIndx)
907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
908   checkConnectivityFullyDefined();
909   int nbOfCells=getNumberOfCells();
910   int nbOfNodes=getNumberOfNodes();
911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
912   int *revNodalIndxPtr=revNodalIndx->getPointer();
913   const int *conn=_nodal_connec->getConstPointer();
914   const int *connIndex=_nodal_connec_index->getConstPointer();
915   std::string name="Mesh constituent of "; name+=getName();
916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
917   ret->setCoords(getCoords());
918   ret->allocateCells(2*nbOfCells);
919   descIndx->alloc(nbOfCells+1,1);
920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
921   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
922   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
923     {
924       int pos=connIndex[eltId];
925       int posP1=connIndex[eltId+1];
926       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
927       SonsGenerator sg(cm);
928       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
929       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
930       for(unsigned i=0;i<nbOfSons;i++)
931         {
932           INTERP_KERNEL::NormalizedCellType cmsId;
933           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
934           for(unsigned k=0;k<nbOfNodesSon;k++)
935             if(tmp[k]>=0)
936               revNodalIndxPtr[tmp[k]+1]++;
937           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
938           revDesc2->pushBackSilent(eltId);
939         }
940       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
941     }
942   int nbOfCellsM1=ret->getNumberOfCells();
943   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
944   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
945   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
946   int *revNodalPtr=revNodal->getPointer();
947   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
948   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
949   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
950     {
951       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
952       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
953       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
954         if(*iter>=0)//for polyhedrons
955           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
956     }
957   //
958   DataArrayInt *commonCells=0,*commonCellsI=0;
959   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
961   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
962   int newNbOfCellsM1=-1;
963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
964                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
965   std::vector<bool> isImpacted(nbOfCellsM1,false);
966   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
967     for(int work2=work[0];work2!=work[1];work2++)
968       isImpacted[commonCellsPtr[work2]]=true;
969   const int *o2nM1Ptr=o2nM1->getConstPointer();
970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
971   const int *n2oM1Ptr=n2oM1->getConstPointer();
972   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
973   ret2->copyTinyInfoFrom(this);
974   desc->alloc(descIndx->back(),1);
975   int *descPtr=desc->getPointer();
976   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
977   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
978     {
979       if(!isImpacted[i])
980         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
981       else
982         {
983           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
984             {
985               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
986               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
987             }
988           else
989             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
990         }
991     }
992   revDesc->reserve(newNbOfCellsM1);
993   revDescIndx->alloc(newNbOfCellsM1+1,1);
994   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
995   const int *revDesc2Ptr=revDesc2->getConstPointer();
996   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
997     {
998       int oldCellIdM1=n2oM1Ptr[i];
999       if(!isImpacted[oldCellIdM1])
1000         {
1001           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1002           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1003         }
1004       else
1005         {
1006           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1007             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1008           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1009           commonCellsIPtr++;
1010         }
1011     }
1012   //
1013   return ret2.retn();
1014 }
1015
1016 struct MEDCouplingAccVisit
1017 {
1018   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1019   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1020   int _new_nb_of_nodes;
1021 };
1022
1023 /// @endcond
1024
1025 /*!
1026  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1027  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1028  * array of cell ids. Pay attention that after conversion all algorithms work slower
1029  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1030  * conversion due presence of invalid ids in the array of cells to convert, as a
1031  * result \a this mesh contains some already converted elements. In this case the 2D
1032  * mesh remains valid but 3D mesh becomes \b inconsistent!
1033  *  \warning This method can significantly modify the order of geometric types in \a this,
1034  *          hence, to write this mesh to the MED file, its cells must be sorted using
1035  *          sortCellsInMEDFileFrmt().
1036  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1037  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1038  *         cellIdsToConvertBg.
1039  *  \throw If the coordinates array is not set.
1040  *  \throw If the nodal connectivity of cells is node defined.
1041  *  \throw If dimension of \a this mesh is not either 2 or 3.
1042  *
1043  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1044  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1045  */
1046 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1047 {
1048   checkFullyDefined();
1049   int dim=getMeshDimension();
1050   if(dim<2 || dim>3)
1051     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1052   int nbOfCells=getNumberOfCells();
1053   if(dim==2)
1054     {
1055       const int *connIndex=_nodal_connec_index->getConstPointer();
1056       int *conn=_nodal_connec->getPointer();
1057       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1058         {
1059           if(*iter>=0 && *iter<nbOfCells)
1060             {
1061               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1062               if(!cm.isDynamic())
1063                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1064               else
1065                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1066             }
1067           else
1068             {
1069               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1070               oss << " in range [0," << nbOfCells << ") !";
1071               throw INTERP_KERNEL::Exception(oss.str().c_str());
1072             }
1073         }
1074     }
1075   else
1076     {
1077       int *connIndex=_nodal_connec_index->getPointer();
1078       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1079       const int *connOld=_nodal_connec->getConstPointer();
1080       int connOldLgth=_nodal_connec->getNbOfElems();
1081       std::vector<int> connNew(connOld,connOld+connOldLgth);
1082       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1083         {
1084           if(*iter>=0 && *iter<nbOfCells)
1085             {
1086               int pos=connIndex[*iter];
1087               int posP1=connIndex[(*iter)+1];
1088               int lgthOld=posP1-pos-1;
1089               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1090               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1091               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1092               int *tmp=new int[nbOfFaces*lgthOld];
1093               int *work=tmp;
1094               for(int j=0;j<(int)nbOfFaces;j++)
1095                 {
1096                   INTERP_KERNEL::NormalizedCellType type;
1097                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1098                   work+=offset;
1099                   *work++=-1;
1100                 }
1101               std::size_t newLgth=std::distance(tmp,work)-1;
1102               std::size_t delta=newLgth-lgthOld;
1103               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1104               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1105               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1106               delete [] tmp;
1107             }
1108           else
1109             {
1110               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1111               oss << " in range [0," << nbOfCells << ") !";
1112               throw INTERP_KERNEL::Exception(oss.str().c_str());
1113             }
1114         }
1115       _nodal_connec->alloc((int)connNew.size(),1);
1116       int *newConnPtr=_nodal_connec->getPointer();
1117       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1118     }
1119   computeTypes();
1120 }
1121
1122 /*!
1123  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1124  * polyhedrons (if \a this is a 3D mesh).
1125  *  \warning As this method is purely for user-friendliness and no optimization is
1126  *          done to avoid construction of a useless vector, this method can be costly
1127  *          in memory.
1128  *  \throw If the coordinates array is not set.
1129  *  \throw If the nodal connectivity of cells is node defined.
1130  *  \throw If dimension of \a this mesh is not either 2 or 3.
1131  */
1132 void MEDCouplingUMesh::convertAllToPoly()
1133 {
1134   int nbOfCells=getNumberOfCells();
1135   std::vector<int> cellIds(nbOfCells);
1136   for(int i=0;i<nbOfCells;i++)
1137     cellIds[i]=i;
1138   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1139 }
1140
1141 /*!
1142  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1143  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1144  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1145  * base facet of the volume and the second half of nodes describes an opposite facet
1146  * having the same number of nodes as the base one. This method converts such
1147  * connectivity to a valid polyhedral format where connectivity of each facet is
1148  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1149  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1150  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1151  * a correct orientation of the first facet of a polyhedron, else orientation of a
1152  * corrected cell is reverse.<br>
1153  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1154  * it releases the user from boring description of polyhedra connectivity in the valid
1155  * format.
1156  *  \throw If \a this->getMeshDimension() != 3.
1157  *  \throw If \a this->getSpaceDimension() != 3.
1158  *  \throw If the nodal connectivity of cells is not defined.
1159  *  \throw If the coordinates array is not set.
1160  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1161  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1162  *
1163  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1164  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1165  */
1166 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1167 {
1168   checkFullyDefined();
1169   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1170     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1171   int nbOfCells=getNumberOfCells();
1172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1173   newCi->alloc(nbOfCells+1,1);
1174   int *newci=newCi->getPointer();
1175   const int *ci=_nodal_connec_index->getConstPointer();
1176   const int *c=_nodal_connec->getConstPointer();
1177   newci[0]=0;
1178   for(int i=0;i<nbOfCells;i++)
1179     {
1180       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1181       if(type==INTERP_KERNEL::NORM_POLYHED)
1182         {
1183           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1184             {
1185               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1186               throw INTERP_KERNEL::Exception(oss.str().c_str());
1187             }
1188           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1189           if(n2%2!=0)
1190             {
1191               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 !";
1192               throw INTERP_KERNEL::Exception(oss.str().c_str());
1193             }
1194           int n1=(int)(n2/2);
1195           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)
1196         }
1197       else
1198         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1199     }
1200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1201   newC->alloc(newci[nbOfCells],1);
1202   int *newc=newC->getPointer();
1203   for(int i=0;i<nbOfCells;i++)
1204     {
1205       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1206       if(type==INTERP_KERNEL::NORM_POLYHED)
1207         {
1208           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1209           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1210           *newc++=-1;
1211           for(std::size_t j=0;j<n1;j++)
1212             {
1213               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1214               newc[n1+5*j]=-1;
1215               newc[n1+5*j+1]=c[ci[i]+1+j];
1216               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1217               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1218               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1219             }
1220           newc+=n1*6;
1221         }
1222       else
1223         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1224     }
1225   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1226   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1227 }
1228
1229
1230 /*!
1231  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1232  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1233  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1234  *          to write this mesh to the MED file, its cells must be sorted using
1235  *          sortCellsInMEDFileFrmt().
1236  * \return \c true if at least one cell has been converted, \c false else. In the
1237  *         last case the nodal connectivity remains unchanged.
1238  * \throw If the coordinates array is not set.
1239  * \throw If the nodal connectivity of cells is not defined.
1240  * \throw If \a this->getMeshDimension() < 0.
1241  */
1242 bool MEDCouplingUMesh::unPolyze()
1243 {
1244   checkFullyDefined();
1245   int mdim=getMeshDimension();
1246   if(mdim<0)
1247     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1248   if(mdim<=1)
1249     return false;
1250   int nbOfCells=getNumberOfCells();
1251   if(nbOfCells<1)
1252     return false;
1253   int initMeshLgth=getMeshLength();
1254   int *conn=_nodal_connec->getPointer();
1255   int *index=_nodal_connec_index->getPointer();
1256   int posOfCurCell=0;
1257   int newPos=0;
1258   int lgthOfCurCell;
1259   bool ret=false;
1260   for(int i=0;i<nbOfCells;i++)
1261     {
1262       lgthOfCurCell=index[i+1]-posOfCurCell;
1263       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1264       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1265       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1266       int newLgth;
1267       if(cm.isDynamic())
1268         {
1269           switch(cm.getDimension())
1270             {
1271             case 2:
1272               {
1273                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1274                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1275                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1276                 break;
1277               }
1278             case 3:
1279               {
1280                 int nbOfFaces,lgthOfPolyhConn;
1281                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1282                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1283                 break;
1284               }
1285             case 1:
1286               {
1287                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1288                 break;
1289               }
1290             }
1291           ret=ret || (newType!=type);
1292           conn[newPos]=newType;
1293           newPos+=newLgth+1;
1294           posOfCurCell=index[i+1];
1295           index[i+1]=newPos;
1296         }
1297       else
1298         {
1299           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1300           newPos+=lgthOfCurCell;
1301           posOfCurCell+=lgthOfCurCell;
1302           index[i+1]=newPos;
1303         }
1304     }
1305   if(newPos!=initMeshLgth)
1306     _nodal_connec->reAlloc(newPos);
1307   if(ret)
1308     computeTypes();
1309   return ret;
1310 }
1311
1312 /*!
1313  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1314  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1315  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1316  *
1317  * \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 
1318  *             precision.
1319  */
1320 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1321 {
1322   checkFullyDefined();
1323   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1325   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1326   coords->recenterForMaxPrecision(eps);
1327   //
1328   int nbOfCells=getNumberOfCells();
1329   const int *conn=_nodal_connec->getConstPointer();
1330   const int *index=_nodal_connec_index->getConstPointer();
1331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1332   connINew->alloc(nbOfCells+1,1);
1333   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1335   bool changed=false;
1336   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1337     {
1338       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1339         {
1340           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1341           changed=true;
1342         }
1343       else
1344         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1345       *connINewPtr=connNew->getNumberOfTuples();
1346     }
1347   if(changed)
1348     setConnectivity(connNew,connINew,false);
1349 }
1350
1351 /*!
1352  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1353  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1354  * the format of returned DataArrayInt instance.
1355  * 
1356  * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1357  * \sa MEDCouplingUMesh::getNodeIdsInUse
1358  */
1359 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1360 {
1361   checkConnectivityFullyDefined();
1362   int nbOfCells=getNumberOfCells();
1363   const int *connIndex=_nodal_connec_index->getConstPointer();
1364   const int *conn=_nodal_connec->getConstPointer();
1365   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1366   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1367   std::vector<bool> retS(maxElt,false);
1368   for(int i=0;i<nbOfCells;i++)
1369     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1370       if(conn[j]>=0)
1371         retS[conn[j]]=true;
1372   int sz=0;
1373   for(int i=0;i<maxElt;i++)
1374     if(retS[i])
1375       sz++;
1376   DataArrayInt *ret=DataArrayInt::New();
1377   ret->alloc(sz,1);
1378   int *retPtr=ret->getPointer();
1379   for(int i=0;i<maxElt;i++)
1380     if(retS[i])
1381       *retPtr++=i;
1382   return ret;
1383 }
1384
1385 /*!
1386  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1387  * \sa MEDCouplingUMesh::getNodeIdsInUse
1388  */
1389 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1390 {
1391   int nbOfNodes=(int)nodeIdsInUse.size();
1392   int nbOfCells=getNumberOfCells();
1393   const int *connIndex=_nodal_connec_index->getConstPointer();
1394   const int *conn=_nodal_connec->getConstPointer();
1395   for(int i=0;i<nbOfCells;i++)
1396     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1397       if(conn[j]>=0)
1398         {
1399           if(conn[j]<nbOfNodes)
1400             nodeIdsInUse[conn[j]]=true;
1401           else
1402             {
1403               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1404               throw INTERP_KERNEL::Exception(oss.str().c_str());
1405             }
1406         }
1407 }
1408
1409 /*!
1410  * Finds nodes not used in any cell and returns an array giving a new id to every node
1411  * by excluding the unused nodes, for which the array holds -1. The result array is
1412  * a mapping in "Old to New" mode. 
1413  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1414  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1415  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1416  *          if the node is unused or a new id else. The caller is to delete this
1417  *          array using decrRef() as it is no more needed.  
1418  *  \throw If the coordinates array is not set.
1419  *  \throw If the nodal connectivity of cells is not defined.
1420  *  \throw If the nodal connectivity includes an invalid id.
1421  *
1422  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1423  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1424  * \sa computeNodeIdsAlg()
1425  */
1426 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1427 {
1428   nbrOfNodesInUse=-1;
1429   int nbOfNodes=getNumberOfNodes();
1430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1431   ret->alloc(nbOfNodes,1);
1432   int *traducer=ret->getPointer();
1433   std::fill(traducer,traducer+nbOfNodes,-1);
1434   int nbOfCells=getNumberOfCells();
1435   const int *connIndex=_nodal_connec_index->getConstPointer();
1436   const int *conn=_nodal_connec->getConstPointer();
1437   for(int i=0;i<nbOfCells;i++)
1438     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1439       if(conn[j]>=0)
1440         {
1441           if(conn[j]<nbOfNodes)
1442             traducer[conn[j]]=1;
1443           else
1444             {
1445               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1446               throw INTERP_KERNEL::Exception(oss.str().c_str());
1447             }
1448         }
1449   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1450   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1451   return ret.retn();
1452 }
1453
1454 /*!
1455  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1456  * For each cell in \b this the number of nodes constituting cell is computed.
1457  * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1458  * For polyhedrons, the face separation (-1) are excluded from the couting.
1459  * 
1460  * \return a newly allocated array
1461  */
1462 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1463 {
1464   checkConnectivityFullyDefined();
1465   int nbOfCells=getNumberOfCells();
1466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1467   ret->alloc(nbOfCells,1);
1468   int *retPtr=ret->getPointer();
1469   const int *conn=getNodalConnectivity()->getConstPointer();
1470   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1471   for(int i=0;i<nbOfCells;i++,retPtr++)
1472     {
1473       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1474         *retPtr=connI[i+1]-connI[i]-1;
1475       else
1476         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1477     }
1478   return ret.retn();
1479 }
1480
1481 /*!
1482  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1483  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1484  * array mean that the corresponding old node is no more used. 
1485  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1486  *           this->getNumberOfNodes() before call of this method. The caller is to
1487  *           delete this array using decrRef() as it is no more needed. 
1488  *  \throw If the coordinates array is not set.
1489  *  \throw If the nodal connectivity of cells is not defined.
1490  *  \throw If the nodal connectivity includes an invalid id.
1491  *
1492  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1493  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1494  */
1495 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1496 {
1497   int newNbOfNodes=-1;
1498   DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1499   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1500   return traducer;
1501 }
1502
1503 /*!
1504  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1505  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1506  */
1507 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1508 {
1509   switch(compType)
1510     {
1511     case 0:
1512       return AreCellsEqual0(conn,connI,cell1,cell2);
1513     case 1:
1514       return AreCellsEqual1(conn,connI,cell1,cell2);
1515     case 2:
1516       return AreCellsEqual2(conn,connI,cell1,cell2);
1517     case 3:
1518       return AreCellsEqual3(conn,connI,cell1,cell2);
1519     case 7:
1520       return AreCellsEqual7(conn,connI,cell1,cell2);
1521     }
1522   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1523 }
1524
1525 /*!
1526  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1527  */
1528 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1529 {
1530   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1531     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1532   return 0;
1533 }
1534
1535 /*!
1536  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1537  */
1538 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1539 {
1540   int sz=connI[cell1+1]-connI[cell1];
1541   if(sz==connI[cell2+1]-connI[cell2])
1542     {
1543       if(conn[connI[cell1]]==conn[connI[cell2]])
1544         {
1545           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1546           unsigned dim=cm.getDimension();
1547           if(dim!=3)
1548             {
1549               if(dim!=1)
1550                 {
1551                   int sz1=2*(sz-1);
1552                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1553                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1554                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1555                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1556                   return work!=tmp+sz1?1:0;
1557                 }
1558               else
1559                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1560             }
1561           else
1562             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1563         }
1564     }
1565   return 0;
1566 }
1567
1568 /*!
1569  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1570  */
1571 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1572 {
1573   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1574     {
1575       if(conn[connI[cell1]]==conn[connI[cell2]])
1576         {
1577           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1578           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1579           return s1==s2?1:0;
1580         }
1581     }
1582   return 0;
1583 }
1584
1585 /*!
1586  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1587  */
1588 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1589 {
1590   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1591     {
1592       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1593       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1594       return s1==s2?1:0;
1595     }
1596   return 0;
1597 }
1598
1599 /*!
1600  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1601  */
1602 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1603 {
1604   int sz=connI[cell1+1]-connI[cell1];
1605   if(sz==connI[cell2+1]-connI[cell2])
1606     {
1607       if(conn[connI[cell1]]==conn[connI[cell2]])
1608         {
1609           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1610           unsigned dim=cm.getDimension();
1611           if(dim!=3)
1612             {
1613               if(dim!=1)
1614                 {
1615                   int sz1=2*(sz-1);
1616                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1617                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1618                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1619                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1620                   if(work!=tmp+sz1)
1621                     return 1;
1622                   else
1623                     {
1624                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1625                       std::reverse_iterator<int *> it2((int *)tmp);
1626                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1627                         return 2;
1628                       else
1629                         return 0;
1630                     }
1631                   
1632                   return work!=tmp+sz1?1:0;
1633                 }
1634               else
1635                 {//case of SEG2 and SEG3
1636                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1637                     return 1;
1638                   if(!cm.isQuadratic())
1639                     {
1640                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1641                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1642                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1643                         return 2;
1644                       return 0;
1645                     }
1646                   else
1647                     {
1648                       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])
1649                         return 2;
1650                       return 0;
1651                     }
1652                 }
1653             }
1654           else
1655             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1656         }
1657     }
1658   return 0;
1659 }
1660
1661
1662 /*!
1663  * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1664  * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1665  */
1666 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1667 {
1668   if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1669     return false;
1670   std::vector<int> c1,c2;
1671   getNodeIdsOfCell(cellId,c1);
1672   other->getNodeIdsOfCell(cellId,c2);
1673   std::size_t sz=c1.size();
1674   if(sz!=c2.size())
1675     return false;
1676   for(std::size_t i=0;i<sz;i++)
1677     {
1678       std::vector<double> n1,n2;
1679       getCoordinatesOfNode(c1[0],n1);
1680       other->getCoordinatesOfNode(c2[0],n2);
1681       std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1682       std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1683       if(*std::max_element(n1.begin(),n1.end())>prec)
1684         return false;
1685     }
1686   return true;
1687 }
1688
1689 /*!
1690  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1691  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1692  * and result remains unchanged.
1693  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1694  * If in 'candidates' pool -1 value is considered as an empty value.
1695  * WARNING this method returns only ONE set of result !
1696  */
1697 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1698 {
1699   if(candidates.size()<1)
1700     return false;
1701   bool ret=false;
1702   std::vector<int>::const_iterator iter=candidates.begin();
1703   int start=(*iter++);
1704   for(;iter!=candidates.end();iter++)
1705     {
1706       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1707       if(status!=0)
1708         {
1709           if(!ret)
1710             {
1711               result->pushBackSilent(start);
1712               ret=true;
1713             }
1714           if(status==1)
1715             result->pushBackSilent(*iter);
1716           else
1717             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1718         }
1719     }
1720   return ret;
1721 }
1722
1723 /*!
1724  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1725  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1726  *
1727  * \param [in] compType input specifying the technique used to compare cells each other.
1728  *   - 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.
1729  *   - 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)
1730  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1731  *   - 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
1732  * can be used for users not sensitive to orientation of cell
1733  * \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.
1734  * \param [out] commonCells
1735  * \param [out] commonCellsI
1736  * \return the correspondance array old to new in a newly allocated array.
1737  * 
1738  */
1739 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1740 {
1741   checkConnectivityFullyDefined();
1742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1743   getReverseNodalConnectivity(revNodal,revNodalI);
1744   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1745 }
1746
1747 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1748                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1749 {
1750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1751   int nbOfCells=nodalI->getNumberOfTuples()-1;
1752   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1753   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1754   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1755   std::vector<bool> isFetched(nbOfCells,false);
1756   if(startCellId==0)
1757     {
1758       for(int i=0;i<nbOfCells;i++)
1759         {
1760           if(!isFetched[i])
1761             {
1762               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1763               std::vector<int> v,v2;
1764               if(connOfNode!=connPtr+connIPtr[i+1])
1765                 {
1766                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1767                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1768                   connOfNode++;
1769                 }
1770               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1771                 if(*connOfNode>=0)
1772                   {
1773                     v=v2;
1774                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1775                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1776                     v2.resize(std::distance(v2.begin(),it));
1777                   }
1778               if(v2.size()>1)
1779                 {
1780                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1781                     {
1782                       int pos=commonCellsI->back();
1783                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1784                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1785                         isFetched[*it]=true;
1786                     }
1787                 }
1788             }
1789         }
1790     }
1791   else
1792     {
1793       for(int i=startCellId;i<nbOfCells;i++)
1794         {
1795           if(!isFetched[i])
1796             {
1797               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1798               std::vector<int> v,v2;
1799               if(connOfNode!=connPtr+connIPtr[i+1])
1800                 {
1801                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1802                   connOfNode++;
1803                 }
1804               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1805                 if(*connOfNode>=0)
1806                   {
1807                     v=v2;
1808                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1809                     v2.resize(std::distance(v2.begin(),it));
1810                   }
1811               if(v2.size()>1)
1812                 {
1813                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1814                     {
1815                       int pos=commonCellsI->back();
1816                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1817                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1818                         isFetched[*it]=true;
1819                     }
1820                 }
1821             }
1822         }
1823     }
1824   commonCellsArr=commonCells.retn();
1825   commonCellsIArr=commonCellsI.retn();
1826 }
1827
1828 /*!
1829  * Removes duplicates of cells from \a this mesh and returns an array mapping between
1830  * new and old cell ids in "Old to New" mode. Nothing is changed in \a this mesh if no
1831  * equal cells found.
1832  *  \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1833  *           to write this mesh to the MED file, its cells must be sorted using
1834  *           sortCellsInMEDFileFrmt().
1835  *  \param [in] compType - specifies a cell comparison technique. Meaning of its
1836  *          valid values [0,1,2] is as follows.
1837  *   - 0 : "exact". Two cells are considered equal \c iff they have exactly same nodal
1838  *         connectivity and type. This is the strongest policy.
1839  *   - 1 : "permuted same orientation". Two cells are considered equal \c iff they
1840  *         are based on same nodes and have the same type and orientation.
1841  *   - 2 : "nodal". Two cells are considered equal \c iff they
1842  *         are based on same nodes and have the same type. This is the weakest
1843  *         policy, it can be used by users not sensitive to cell orientation.
1844  *  \param [in] startCellId - specifies the cell id at which search for equal cells
1845  *         starts. By default it is 0, which means that all cells in \a this will be
1846  *         scanned. 
1847  *  \return DataArrayInt - a new instance of DataArrayInt, of length \a
1848  *           this->getNumberOfCells() before call of this method. The caller is to
1849  *           delete this array using decrRef() as it is no more needed. 
1850  *  \throw If the coordinates array is not set.
1851  *  \throw If the nodal connectivity of cells is not defined.
1852  *  \throw If the nodal connectivity includes an invalid id.
1853  *
1854  *  \ref cpp_mcumesh_zipConnectivityTraducer "Here is a C++ example".<br>
1855  *  \ref  py_mcumesh_zipConnectivityTraducer "Here is a Python example".
1856  */
1857 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1858 {
1859   DataArrayInt *commonCells=0,*commonCellsI=0;
1860   findCommonCells(compType,startCellId,commonCells,commonCellsI);
1861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1862   int newNbOfCells=-1;
1863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1864                                                                                                           commonCellsI->end(),newNbOfCells);
1865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1866   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1867   setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1868   return ret.retn();
1869 }
1870
1871 /*!
1872  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1873  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1874  * than \a other->getNumberOfCells() in the returned array means that there is no
1875  * corresponding cell in \a this mesh.
1876  * It is expected that \a this and \a other meshes share the same node coordinates
1877  * array, if it is not so an exception is thrown. 
1878  *  \param [in] other - the mesh to compare with.
1879  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1880  *         valid values [0,1,2], see zipConnectivityTraducer().
1881  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1882  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1883  *         values. The caller is to delete this array using
1884  *         decrRef() as it is no more needed.
1885  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1886  *         mesh.
1887  *
1888  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1889  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1890  *  \sa checkDeepEquivalOnSameNodesWith()
1891  *  \sa checkGeoEquivalWith()
1892  */
1893 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1894 {
1895   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1896   int nbOfCells=getNumberOfCells();
1897   static const int possibleCompType[]={0,1,2};
1898   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1899     {
1900       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1901       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1902       oss << " !";
1903       throw INTERP_KERNEL::Exception(oss.str().c_str());
1904     }
1905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1906   arr=o2n->substr(nbOfCells);
1907   arr->setName(other->getName());
1908   int tmp;
1909   if(other->getNumberOfCells()==0)
1910     return true;
1911   return arr->getMaxValue(tmp)<nbOfCells;
1912 }
1913
1914 /*!
1915  * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1916  * This method tries to determine if \b other is fully included in \b this.
1917  * The main difference is that this method is not expected to throw exception.
1918  * This method has two outputs :
1919  *
1920  * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1921  * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1922  */
1923 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1924 {
1925   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1926   DataArrayInt *commonCells=0,*commonCellsI=0;
1927   int thisNbCells=getNumberOfCells();
1928   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1930   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1931   int otherNbCells=other->getNumberOfCells();
1932   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1933   arr2->alloc(otherNbCells,1);
1934   arr2->fillWithZero();
1935   int *arr2Ptr=arr2->getPointer();
1936   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1937   for(int i=0;i<nbOfCommon;i++)
1938     {
1939       int start=commonCellsPtr[commonCellsIPtr[i]];
1940       if(start<thisNbCells)
1941         {
1942           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1943             {
1944               int sig=commonCellsPtr[j]>0?1:-1;
1945               int val=std::abs(commonCellsPtr[j])-1;
1946               if(val>=thisNbCells)
1947                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1948             }
1949         }
1950     }
1951   arr2->setName(other->getName());
1952   if(arr2->presenceOfValue(0))
1953     return false;
1954   arr=arr2.retn();
1955   return true;
1956 }
1957
1958 /*!
1959  * Merges nodes equal within \a precision and returns an array describing the 
1960  * permutation used to remove duplicate nodes.
1961  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1962  *              considered not coincident.
1963  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1964  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1965  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1966  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1967  *          is to delete this array using decrRef() as it is no more needed.
1968  *  \throw If the coordinates array is not set.
1969  *  \throw If the nodal connectivity of cells is not defined.
1970  *
1971  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1972  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1973  */
1974 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1975 {
1976   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1977   if(areNodesMerged)
1978     renumberNodes(ret->getConstPointer(),newNbOfNodes);
1979   return ret;
1980 }
1981
1982
1983 /*!
1984  * Merges nodes equal within \a precision and returns an array describing the 
1985  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1986  *  of merged nodes is changed to be at their barycenter.
1987  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1988  *              considered not coincident.
1989  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1990  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1991  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1992  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1993  *          is to delete this array using decrRef() as it is no more needed.
1994  *  \throw If the coordinates array is not set.
1995  *  \throw If the nodal connectivity of cells is not defined.
1996  *
1997  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1998  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1999  */
2000 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
2001 {
2002   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
2003   if(areNodesMerged)
2004     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
2005   return ret;
2006 }
2007
2008 /*!
2009  * Substitutes node coordinates array of \a this mesh with that of \a other mesh
2010  * (i.e. \a this->_coords with \a other._coords) provided that coordinates of the two
2011  * meshes match with a specified precision, else an exception is thrown and \a this
2012  * remains unchanged. In case of success the nodal connectivity of \a this mesh
2013  * is permuted according to new order of nodes.
2014  * Contrary to tryToShareSameCoords() this method makes a deeper analysis of
2015  * coordinates (and so more expensive) than simple equality.
2016  *  \param [in] other - the other mesh whose node coordinates array will be used by
2017  *         \a this mesh in case of their equality.
2018  *  \param [in] epsilon - the precision used to compare coordinates (using infinite norm).
2019  *  \throw If the coordinates array of \a this is not set.
2020  *  \throw If the coordinates array of \a other is not set.
2021  *  \throw If the coordinates of \a this and \a other do not match.
2022  */
2023 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
2024 {
2025   const DataArrayDouble *coords=other.getCoords();
2026   if(!coords)
2027     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
2028   if(!_coords)
2029     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
2030   int otherNbOfNodes=other.getNumberOfNodes();
2031   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
2032   _coords->incrRef();
2033   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
2034   setCoords(newCoords);
2035   bool areNodesMerged;
2036   int newNbOfNodes;
2037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
2038   if(!areNodesMerged)
2039     {
2040       setCoords(oldCoords);
2041       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
2042     }
2043   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
2044   const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
2045   if(pt!=da->getConstPointer()+da->getNbOfElems())
2046     {
2047       setCoords(oldCoords);
2048       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
2049     }
2050   setCoords(oldCoords);
2051   renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
2052   setCoords(coords);
2053 }
2054
2055 /*!
2056  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2057  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2058  * cellIds is not given explicitely but by a range python like.
2059  * 
2060  * \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.
2061  * \return a newly allocated
2062  * 
2063  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2064  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2065  */
2066 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
2067 {
2068   if(getMeshDimension()!=-1)
2069     {
2070       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
2071       if(!keepCoords)
2072         ret->zipCoords();
2073       return ret;
2074     }
2075   else
2076     {
2077       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2078       if(newNbOfCells!=1)
2079         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2080       if(start!=0)
2081         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2082       incrRef();
2083       return const_cast<MEDCouplingUMesh *>(this);
2084     }
2085 }
2086
2087 /*!
2088  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2089  * The result mesh shares or not the node coordinates array with \a this mesh depending
2090  * on \a keepCoords parameter.
2091  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2092  *           to write this mesh to the MED file, its cells must be sorted using
2093  *           sortCellsInMEDFileFrmt().
2094  *  \param [in] begin - an array of cell ids to include to the new mesh.
2095  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2096  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2097  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2098  *         by calling zipCoords().
2099  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2100  *         to delete this mesh using decrRef() as it is no more needed. 
2101  *  \throw If the coordinates array is not set.
2102  *  \throw If the nodal connectivity of cells is not defined.
2103  *  \throw If any cell id in the array \a begin is not valid.
2104  *
2105  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2106  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2107  */
2108 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2109 {
2110   if(getMeshDimension()!=-1)
2111     {
2112       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
2113       if(!keepCoords)
2114         ret->zipCoords();
2115       return ret;
2116     }
2117   else
2118     {
2119       if(end-begin!=1)
2120         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2121       if(begin[0]!=0)
2122         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2123       incrRef();
2124       return const_cast<MEDCouplingUMesh *>(this);
2125     }
2126 }
2127
2128 /*!
2129  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2130  *
2131  * 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.
2132  * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2133  * The number of cells of \b this will remain the same with this method.
2134  *
2135  * \param [in] begin begin of cell ids (included) of cells in this to assign
2136  * \param [in] end end of cell ids (excluded) of cells in this to assign
2137  * \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).
2138  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2139  */
2140 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2141 {
2142   checkConnectivityFullyDefined();
2143   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2144   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2146   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2147     {
2148       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2149       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2150       throw INTERP_KERNEL::Exception(oss.str().c_str());
2151     }
2152   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2153   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2154     {
2155       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2156       throw INTERP_KERNEL::Exception(oss.str().c_str());
2157     }
2158   int nbOfCells=getNumberOfCells();
2159   bool easyAssign=true;
2160   const int *connI=_nodal_connec_index->getConstPointer();
2161   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2162   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2163     {
2164       if(*it>=0 && *it<nbOfCells)
2165         {
2166           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2167         }
2168       else
2169         {
2170           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2171           throw INTERP_KERNEL::Exception(oss.str().c_str());
2172         }
2173     }
2174   if(easyAssign)
2175     {
2176       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2177       computeTypes();
2178     }
2179   else
2180     {
2181       DataArrayInt *arrOut=0,*arrIOut=0;
2182       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2183                                                arrOut,arrIOut);
2184       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2185       setConnectivity(arrOut,arrIOut,true);
2186     }
2187 }
2188
2189 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2190 {
2191   checkConnectivityFullyDefined();
2192   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2193   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2195   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2196     {
2197       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2198       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2199       throw INTERP_KERNEL::Exception(oss.str().c_str());
2200     }
2201   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2202   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2203     {
2204       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2205       throw INTERP_KERNEL::Exception(oss.str().c_str());
2206     }
2207   int nbOfCells=getNumberOfCells();
2208   bool easyAssign=true;
2209   const int *connI=_nodal_connec_index->getConstPointer();
2210   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2211   int it=start;
2212   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2213     {
2214       if(it>=0 && it<nbOfCells)
2215         {
2216           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2217         }
2218       else
2219         {
2220           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2221           throw INTERP_KERNEL::Exception(oss.str().c_str());
2222         }
2223     }
2224   if(easyAssign)
2225     {
2226       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2227       computeTypes();
2228     }
2229   else
2230     {
2231       DataArrayInt *arrOut=0,*arrIOut=0;
2232       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2233                                                 arrOut,arrIOut);
2234       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2235       setConnectivity(arrOut,arrIOut,true);
2236     }
2237 }                      
2238
2239 /*!
2240  * Finds cells whose all nodes are in a given array of node ids.
2241  *  \param [in] partBg - the array of node ids.
2242  *  \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2243  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2244  *          cells. The caller is to delete this array using decrRef() as it is no
2245  *          more needed.
2246  *  \throw If the coordinates array is not set.
2247  *  \throw If the nodal connectivity of cells is not defined.
2248  *  \throw If any cell id in \a partBg is not valid.
2249  *
2250  *  \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2251  *  \ref  py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2252  */
2253 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2254 {
2255   DataArrayInt *cellIdsKept=0;
2256   fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2257   cellIdsKept->setName(getName());
2258   return cellIdsKept;
2259 }
2260
2261 /*!
2262  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2263  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2264  * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2265  * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2266  *
2267  * \param [in] begin input start of array of node ids.
2268  * \param [in] end input end of array of node ids.
2269  * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
2270  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2271  */
2272 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2273 {
2274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2275   checkConnectivityFullyDefined();
2276   int tmp=-1;
2277   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2278   std::vector<bool> fastFinder(sz,false);
2279   for(const int *work=begin;work!=end;work++)
2280     if(*work>=0 && *work<sz)
2281       fastFinder[*work]=true;
2282   int nbOfCells=getNumberOfCells();
2283   const int *conn=getNodalConnectivity()->getConstPointer();
2284   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2285   for(int i=0;i<nbOfCells;i++)
2286     {
2287       int ref=0,nbOfHit=0;
2288       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2289         if(*work2>=0)
2290           {
2291             ref++;
2292             if(fastFinder[*work2])
2293               nbOfHit++;
2294           }
2295       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2296         cellIdsKept->pushBackSilent(i);
2297     }
2298   cellIdsKeptArr=cellIdsKept.retn();
2299 }
2300
2301 /*!
2302  * Finds cells whose all or some nodes are in a given array of node ids.
2303  *  \param [in] begin - the array of node ids.
2304  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2305  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2306  *         array \a begin are returned only, else cells whose any node is in the
2307  *         array \a begin are returned.
2308  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2309  *         cells. The caller is to delete this array using decrRef() as it is no more
2310  *         needed. 
2311  *  \throw If the coordinates array is not set.
2312  *  \throw If the nodal connectivity of cells is not defined.
2313  *  \throw If any cell id in \a begin is not valid.
2314  *
2315  *  \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2316  *  \ref  py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2317  */
2318 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2319 {
2320   DataArrayInt *cellIdsKept=0;
2321   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2322   cellIdsKept->setName(getName());
2323   return cellIdsKept;
2324 }
2325
2326 /*!
2327  Creates a new MEDCouplingUMesh containing some cells of \a this mesh. The cells to
2328  copy are selected basing on specified node ids and the value of \a fullyIn
2329  parameter. If \a fullyIn ==\c true, a cell is copied if its all nodes are in the 
2330  array \a begin of node ids. If \a fullyIn ==\c false, a cell is copied if any its
2331  node is in the array of node ids. The created mesh shares the node coordinates array
2332  with \a this mesh.
2333  *  \param [in] begin - the array of node ids.
2334  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2335  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2336  *         array \a begin are copied, else cells whose any node is in the
2337  *         array \a begin are copied.
2338  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2339  *         to delete this mesh using decrRef() as it is no more needed. 
2340  *  \throw If the coordinates array is not set.
2341  *  \throw If the nodal connectivity of cells is not defined.
2342  *  \throw If any node id in \a begin is not valid.
2343  *
2344  *  \ref cpp_mcumesh_buildPartOfMySelfNode "Here is a C++ example".<br>
2345  *  \ref  py_mcumesh_buildPartOfMySelfNode "Here is a Python example".
2346  */
2347 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2348 {
2349   DataArrayInt *cellIdsKept=0;
2350   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2352   return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2353 }
2354
2355 /*!
2356  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2357  * this->getMeshDimension(), that bound some cells of \a this mesh.
2358  * The cells of lower dimension to include to the result mesh are selected basing on
2359  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2360  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2361  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2362  * created mesh shares the node coordinates array with \a this mesh. 
2363  *  \param [in] begin - the array of node ids.
2364  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2365  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2366  *         array \a begin are added, else cells whose any node is in the
2367  *         array \a begin are added.
2368  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2369  *         to delete this mesh using decrRef() as it is no more needed. 
2370  *  \throw If the coordinates array is not set.
2371  *  \throw If the nodal connectivity of cells is not defined.
2372  *  \throw If any node id in \a begin is not valid.
2373  *
2374  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2375  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2376  */
2377 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2378 {
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2380   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2381   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2382   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2383   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2384 }
2385
2386 /*!
2387  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2388  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2389  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2390  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2391  *         by calling zipCoords().
2392  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2393  *         to delete this mesh using decrRef() as it is no more needed. 
2394  *  \throw If the coordinates array is not set.
2395  *  \throw If the nodal connectivity of cells is not defined.
2396  *
2397  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2398  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2399  */
2400 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2401 {
2402   DataArrayInt *desc=DataArrayInt::New();
2403   DataArrayInt *descIndx=DataArrayInt::New();
2404   DataArrayInt *revDesc=DataArrayInt::New();
2405   DataArrayInt *revDescIndx=DataArrayInt::New();
2406   //
2407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2408   revDesc->decrRef();
2409   desc->decrRef();
2410   descIndx->decrRef();
2411   int nbOfCells=meshDM1->getNumberOfCells();
2412   const int *revDescIndxC=revDescIndx->getConstPointer();
2413   std::vector<int> boundaryCells;
2414   for(int i=0;i<nbOfCells;i++)
2415     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2416       boundaryCells.push_back(i);
2417   revDescIndx->decrRef();
2418   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2419   return ret;
2420 }
2421
2422 /*!
2423  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2424  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2425  * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown. 
2426  */
2427 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2428 {
2429   checkFullyDefined();
2430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2434   //
2435   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2436   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2437   //
2438   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2440   const int *revDescPtr=revDesc->getConstPointer();
2441   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2442   int nbOfCells=getNumberOfCells();
2443   std::vector<bool> ret1(nbOfCells,false);
2444   int sz=0;
2445   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2446     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2447       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2448   //
2449   DataArrayInt *ret2=DataArrayInt::New();
2450   ret2->alloc(sz,1);
2451   int *ret2Ptr=ret2->getPointer();
2452   sz=0;
2453   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2454     if(*it)
2455       *ret2Ptr++=sz;
2456   ret2->setName("BoundaryCells");
2457   return ret2;
2458 }
2459
2460 /*!
2461  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2462  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2463  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2464  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2465  *
2466  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2467  * This method method returns cells ids set s = s1 + s2 where :
2468  * 
2469  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2470  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2471  *
2472  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2473  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2474  *
2475  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2476  * \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
2477  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2478  */
2479 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2480 {
2481   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2483   checkConnectivityFullyDefined();
2484   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2485   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2489   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2491   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2492   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2493   DataArrayInt *idsOtherInConsti=0;
2494   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2495   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2496   if(!b)
2497     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2498   std::set<int> s1;
2499   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2500     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2501   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2502   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2503   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2504   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2505   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2506   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2507   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2508   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2509   neighThisPartAuto=0;
2510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2511   const int li[2]={0,1};
2512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2513   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2515   s_renum1->sort();
2516   //
2517   cellIdsRk0=s0arr.retn();
2518   cellIdsRk1=s_renum1.retn();
2519 }
2520
2521 /*!
2522  * 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
2523  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2524  * 
2525  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2526  */
2527 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2528 {
2529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2530   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2533   //
2534   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2535   revDesc=0; desc=0; descIndx=0;
2536   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2538   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2539 }
2540
2541 /*!
2542  * Finds nodes lying on the boundary of \a this mesh.
2543  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2544  *          nodes. The caller is to delete this array using decrRef() as it is no
2545  *          more needed 
2546  *  \throw If the coordinates array is not set.
2547  *  \throw If the nodal connectivity of cells is node defined.
2548  *
2549  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2550  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2551  */
2552 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2553 {
2554   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2555   return skin->computeFetchedNodeIds();
2556 }
2557
2558 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2559 {
2560   incrRef();
2561   return const_cast<MEDCouplingUMesh *>(this);
2562 }
2563
2564 /*!
2565  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2566  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2567  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2568  * array is modified accordingly.
2569  *  \param [in] newNodeNumbers - a permutation array, of length \a
2570  *         this->getNumberOfNodes(), in "Old to New" mode. 
2571  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2572  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering.
2573  *  \throw If the coordinates array is not set.
2574  *  \throw If the nodal connectivity of cells is not defined.
2575  *
2576  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2577  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2578  */
2579 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2580 {
2581   MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2582   renumberNodesInConn(newNodeNumbers);
2583 }
2584
2585 /*!
2586  * Permutes and possibly removes nodes as specified by \a newNodeNumbers array.
2587  * If \a newNodeNumbers[ i ] < 0 then the i-th node is removed, 
2588  * else \a newNodeNumbers[ i ] is a new id of the i-th node. The nodal connectivity
2589  * array is modified accordingly. In contrast to renumberNodes(), location
2590  * of merged nodes (whose new ids coincide) is changed to be at their barycenter.
2591  *  \param [in] newNodeNumbers - a permutation array, of length \a
2592  *         this->getNumberOfNodes(), in "Old to New" mode. 
2593  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2594  *  \param [in] newNbOfNodes - number of nodes remaining after renumbering, which is
2595  *         actually one more than the maximal id in \a newNodeNumbers.
2596  *  \throw If the coordinates array is not set.
2597  *  \throw If the nodal connectivity of cells is not defined.
2598  *
2599  *  \ref cpp_mcumesh_renumberNodes "Here is a C++ example".<br>
2600  *  \ref  py_mcumesh_renumberNodes "Here is a Python example".
2601  */
2602 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2603 {
2604   MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2605   renumberNodesInConn(newNodeNumbers);
2606 }
2607
2608 /*!
2609  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2610  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2611  * 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.
2612  * 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.
2613  * 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.
2614  *
2615  * \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
2616  *             parameter is altered during the call.
2617  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2618  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2619  * \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.
2620  *
2621  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2622  */
2623 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2624                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2625 {
2626   checkFullyDefined();
2627   otherDimM1OnSameCoords.checkFullyDefined();
2628   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2629     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2630   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2631     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2632   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2633   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2636   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2637   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2641   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2642   //
2643   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2645   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2646   DataArrayInt *idsTmp=0;
2647   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2648   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2649   if(!b)
2650     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2651   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2652   DataArrayInt *tmp0=0,*tmp1=0;
2653   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2654   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2658   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2659   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2660   //
2661   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2662   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2663   nodeIdsToDuplicate=s3.retn();
2664 }
2665
2666 /*!
2667  * This method operates a modification of the connectivity and coords in \b this.
2668  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2669  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2670  * 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
2671  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2672  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2673  * 
2674  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2675  * 
2676  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2677  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2678  */
2679 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2680 {
2681   int nbOfNodes=getNumberOfNodes();
2682   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2683   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2684 }
2685
2686 /*!
2687  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2688  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2689  * This method is a generalization of shiftNodeNumbersInConn().
2690  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2691  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2692  *         this->getNumberOfNodes(), in "Old to New" mode. 
2693  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2694  *  \throw If the nodal connectivity of cells is not defined.
2695  *
2696  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2697  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2698  */
2699 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2700 {
2701   checkConnectivityFullyDefined();
2702   int *conn=getNodalConnectivity()->getPointer();
2703   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2704   int nbOfCells=getNumberOfCells();
2705   for(int i=0;i<nbOfCells;i++)
2706     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2707       {
2708         int& node=conn[iconn];
2709         if(node>=0)//avoid polyhedron separator
2710           {
2711             node=newNodeNumbersO2N[node];
2712           }
2713       }
2714   _nodal_connec->declareAsNew();
2715   updateTime();
2716 }
2717
2718 /*!
2719  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2720  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2721  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2722  * 
2723  * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2724  */
2725 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2726 {
2727   checkConnectivityFullyDefined();
2728   int *conn=getNodalConnectivity()->getPointer();
2729   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2730   int nbOfCells=getNumberOfCells();
2731   for(int i=0;i<nbOfCells;i++)
2732     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2733       {
2734         int& node=conn[iconn];
2735         if(node>=0)//avoid polyhedron separator
2736           {
2737             node+=delta;
2738           }
2739       }
2740   _nodal_connec->declareAsNew();
2741   updateTime();
2742 }
2743
2744 /*!
2745  * This method operates a modification of the connectivity in \b this.
2746  * 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.
2747  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2748  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2749  * 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
2750  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2751  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2752  * 
2753  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2754  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2755  * 
2756  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2757  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2758  * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd). 
2759  */
2760 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2761 {
2762   checkConnectivityFullyDefined();
2763   std::map<int,int> m;
2764   int val=offset;
2765   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2766     m[*work]=val;
2767   int *conn=getNodalConnectivity()->getPointer();
2768   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2769   int nbOfCells=getNumberOfCells();
2770   for(int i=0;i<nbOfCells;i++)
2771     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2772       {
2773         int& node=conn[iconn];
2774         if(node>=0)//avoid polyhedron separator
2775           {
2776             std::map<int,int>::iterator it=m.find(node);
2777             if(it!=m.end())
2778               node=(*it).second;
2779           }
2780       }
2781   updateTime();
2782 }
2783
2784 /*!
2785  * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2786  *
2787  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2788  * After the call of this method the number of cells remains the same as before.
2789  *
2790  * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2791  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2792  * be strictly in [0;this->getNumberOfCells()).
2793  *
2794  * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2795  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2796  * should be contained in[0;this->getNumberOfCells()).
2797  * 
2798  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2799  */
2800 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2801 {
2802   checkConnectivityFullyDefined();
2803   int nbCells=getNumberOfCells();
2804   const int *array=old2NewBg;
2805   if(check)
2806     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2807   //
2808   const int *conn=_nodal_connec->getConstPointer();
2809   const int *connI=_nodal_connec_index->getConstPointer();
2810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2811   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2812   newConn->copyStringInfoFrom(*_nodal_connec);
2813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2814   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2815   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2816   //
2817   int *newC=newConn->getPointer();
2818   int *newCI=newConnI->getPointer();
2819   int loc=0;
2820   newCI[0]=loc;
2821   for(int i=0;i<nbCells;i++)
2822     {
2823       std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2824       int nbOfElts=connI[pos+1]-connI[pos];
2825       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2826       loc+=nbOfElts;
2827       newCI[i+1]=loc;
2828     }
2829   //
2830   setConnectivity(newConn,newConnI);
2831   if(check)
2832     delete [] const_cast<int *>(array);
2833 }
2834
2835 /*!
2836  * Finds cells whose bounding boxes intersect a given bounding box.
2837  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2838  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2839  *         zMax (if in 3D). 
2840  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2841  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2842  *         extent of the bounding box of cell to produce an addition to this bounding box.
2843  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2844  *         cells. The caller is to delete this array using decrRef() as it is no more
2845  *         needed. 
2846  *  \throw If the coordinates array is not set.
2847  *  \throw If the nodal connectivity of cells is not defined.
2848  *
2849  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2850  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2851  */
2852 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2853 {
2854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2855   if(getMeshDimension()==-1)
2856     {
2857       elems->pushBackSilent(0);
2858       return elems.retn();
2859     }
2860   int dim=getSpaceDimension();
2861   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2862   const int* conn      = getNodalConnectivity()->getConstPointer();
2863   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2864   const double* coords = getCoords()->getConstPointer();
2865   int nbOfCells=getNumberOfCells();
2866   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2867     {
2868       for (int i=0; i<dim; i++)
2869         {
2870           elem_bb[i*2]=std::numeric_limits<double>::max();
2871           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2872         }
2873
2874       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2875         {
2876           int node= conn[inode];
2877           if(node>=0)//avoid polyhedron separator
2878             {
2879               for (int idim=0; idim<dim; idim++)
2880                 {
2881                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2882                     {
2883                       elem_bb[idim*2] = coords[node*dim+idim] ;
2884                     }
2885                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2886                     {
2887                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2888                     }
2889                 }
2890             }
2891         }
2892       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2893         elems->pushBackSilent(ielem);
2894     }
2895   return elems.retn();
2896 }
2897
2898 /*!
2899  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2900  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2901  * added in 'elems' parameter.
2902  */
2903 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2904 {
2905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2906   if(getMeshDimension()==-1)
2907     {
2908       elems->pushBackSilent(0);
2909       return elems.retn();
2910     }
2911   int dim=getSpaceDimension();
2912   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2913   const int* conn      = getNodalConnectivity()->getConstPointer();
2914   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2915   const double* coords = getCoords()->getConstPointer();
2916   int nbOfCells=getNumberOfCells();
2917   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2918     {
2919       for (int i=0; i<dim; i++)
2920         {
2921           elem_bb[i*2]=std::numeric_limits<double>::max();
2922           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2923         }
2924
2925       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2926         {
2927           int node= conn[inode];
2928           if(node>=0)//avoid polyhedron separator
2929             {
2930               for (int idim=0; idim<dim; idim++)
2931                 {
2932                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2933                     {
2934                       elem_bb[idim*2] = coords[node*dim+idim] ;
2935                     }
2936                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2937                     {
2938                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2939                     }
2940                 }
2941             }
2942         }
2943       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2944         elems->pushBackSilent(ielem);
2945     }
2946   return elems.retn();
2947 }
2948
2949 /*!
2950  * Returns a type of a cell by its id.
2951  *  \param [in] cellId - the id of the cell of interest.
2952  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2953  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2954  */
2955 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2956 {
2957   const int *ptI=_nodal_connec_index->getConstPointer();
2958   const int *pt=_nodal_connec->getConstPointer();
2959   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2960     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2961   else
2962     {
2963       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2964       throw INTERP_KERNEL::Exception(oss.str().c_str());
2965     }
2966 }
2967
2968 /*!
2969  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2970  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2971  * The coordinates array is not considered here.
2972  *
2973  * \param [in] type the geometric type
2974  * \return cell ids in this having geometric type \a type.
2975  */
2976 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2977 {
2978   
2979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2980   ret->alloc(0,1);
2981   checkConnectivityFullyDefined();
2982   int nbCells=getNumberOfCells();
2983   int mdim=getMeshDimension();
2984   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2985   if(mdim!=(int)cm.getDimension())
2986     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2987   const int *ptI=_nodal_connec_index->getConstPointer();
2988   const int *pt=_nodal_connec->getConstPointer();
2989   for(int i=0;i<nbCells;i++)
2990     {
2991       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2992         ret->pushBackSilent(i);
2993     }
2994   return ret.retn();
2995 }
2996
2997 /*!
2998  * Returns nb of cells having the geometric type 'type'.
2999  */
3000 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3001 {
3002   const int *ptI=_nodal_connec_index->getConstPointer();
3003   const int *pt=_nodal_connec->getConstPointer();
3004   int nbOfCells=getNumberOfCells();
3005   int ret=0;
3006   for(int i=0;i<nbOfCells;i++)
3007     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3008       ret++;
3009   return ret;
3010 }
3011
3012 /*!
3013  * Returns the nodal connectivity of a given cell.
3014  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3015  * all returned node ids can be used in getCoordinatesOfNode().
3016  *  \param [in] cellId - an id of the cell of interest.
3017  *  \param [in,out] conn - a vector where the node ids are appended. It is not
3018  *         cleared before the appending.
3019  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3020  */
3021 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3022 {
3023   const int *ptI=_nodal_connec_index->getConstPointer();
3024   const int *pt=_nodal_connec->getConstPointer();
3025   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3026     if(*w>=0)
3027       conn.push_back(*w);
3028 }
3029
3030 std::string MEDCouplingUMesh::simpleRepr() const
3031 {
3032   static const char msg0[]="No coordinates specified !";
3033   std::ostringstream ret;
3034   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3035   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3036   int tmpp1,tmpp2;
3037   double tt=getTime(tmpp1,tmpp2);
3038   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3039   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3040   if(_mesh_dim>=-1)
3041     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3042   else
3043     { ret << " Mesh dimension has not been set or is invalid !"; }
3044   if(_coords!=0)
3045     {
3046       const int spaceDim=getSpaceDimension();
3047       ret << spaceDim << "\nInfo attached on space dimension : ";
3048       for(int i=0;i<spaceDim;i++)
3049         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3050       ret << "\n";
3051     }
3052   else
3053     ret << msg0 << "\n";
3054   ret << "Number of nodes : ";
3055   if(_coords!=0)
3056     ret << getNumberOfNodes() << "\n";
3057   else
3058     ret << msg0 << "\n";
3059   ret << "Number of cells : ";
3060   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3061     ret << getNumberOfCells() << "\n";
3062   else
3063     ret << "No connectivity specified !" << "\n";
3064   ret << "Cell types present : ";
3065   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3066     {
3067       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3068       ret << cm.getRepr() << " ";
3069     }
3070   ret << "\n";
3071   return ret.str();
3072 }
3073
3074 std::string MEDCouplingUMesh::advancedRepr() const
3075 {
3076   std::ostringstream ret;
3077   ret << simpleRepr();
3078   ret << "\nCoordinates array : \n___________________\n\n";
3079   if(_coords)
3080     _coords->reprWithoutNameStream(ret);
3081   else
3082     ret << "No array set !\n";
3083   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3084   reprConnectivityOfThisLL(ret);
3085   return ret.str();
3086 }
3087
3088 /*!
3089  * This method returns a C++ code that is a dump of \a this.
3090  * This method will throw if this is not fully defined.
3091  */
3092 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
3093 {
3094   static const char coordsName[]="coords";
3095   static const char connName[]="conn";
3096   static const char connIName[]="connI";
3097   checkFullyDefined();
3098   std::ostringstream ret; ret << "// coordinates" << std::endl;
3099   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3100   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3101   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3102   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3103   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3104   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3105   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3106   return ret.str();
3107 }
3108
3109 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3110 {
3111   std::ostringstream ret;
3112   reprConnectivityOfThisLL(ret);
3113   return ret.str();
3114 }
3115
3116 /*!
3117  * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
3118  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3119  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3120  * some algos).
3121  * 
3122  * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3123  * 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
3124  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3125  */
3126 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
3127 {
3128   int mdim=getMeshDimension();
3129   if(mdim<0)
3130     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3131   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3133   bool needToCpyCT=true;
3134   if(!_nodal_connec)
3135     {
3136       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3137       needToCpyCT=false;
3138     }
3139   else
3140     {
3141       tmp1=_nodal_connec;
3142       tmp1->incrRef();
3143     }
3144   if(!_nodal_connec_index)
3145     {
3146       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3147       needToCpyCT=false;
3148     }
3149   else
3150     {
3151       tmp2=_nodal_connec_index;
3152       tmp2->incrRef();
3153     }
3154   ret->setConnectivity(tmp1,tmp2,false);
3155   if(needToCpyCT)
3156     ret->_types=_types;
3157   if(!_coords)
3158     {
3159       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3160       ret->setCoords(coords);
3161     }
3162   else
3163     ret->setCoords(_coords);
3164   return ret.retn();
3165 }
3166
3167 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3168 {
3169   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3170     {
3171       int nbOfCells=getNumberOfCells();
3172       const int *c=_nodal_connec->getConstPointer();
3173       const int *ci=_nodal_connec_index->getConstPointer();
3174       for(int i=0;i<nbOfCells;i++)
3175         {
3176           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3177           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3178           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3179           stream << "\n";
3180         }
3181     }
3182   else
3183     stream << "Connectivity not defined !\n";
3184 }
3185
3186 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3187 {
3188   const int *ptI=_nodal_connec_index->getConstPointer();
3189   const int *pt=_nodal_connec->getConstPointer();
3190   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3191     return ptI[cellId+1]-ptI[cellId]-1;
3192   else
3193     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3194 }
3195
3196 /*!
3197  * Returns types of cells of the specified part of \a this mesh.
3198  * This method avoids computing sub-mesh explicitely to get its types.
3199  *  \param [in] begin - an array of cell ids of interest.
3200  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3201  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3202  *         describing the cell types. 
3203  *  \throw If the coordinates array is not set.
3204  *  \throw If the nodal connectivity of cells is not defined.
3205  *  \sa getAllTypes()
3206  */
3207 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
3208 {
3209   checkFullyDefined();
3210   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3211   const int *conn=_nodal_connec->getConstPointer();
3212   const int *connIndex=_nodal_connec_index->getConstPointer();
3213   for(const int *w=begin;w!=end;w++)
3214     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3215   return ret;
3216 }
3217
3218 /*!
3219  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3220  * a set of types of cells constituting \a this mesh. 
3221  * This method is for advanced users having prepared their connectivity before. For
3222  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3223  *  \param [in] conn - the nodal connectivity array. 
3224  *  \param [in] connIndex - the nodal connectivity index array.
3225  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3226  *         mesh is updated.
3227  */
3228 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3229 {
3230   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3231   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3232   if(isComputingTypes)
3233     computeTypes();
3234   declareAsNew();
3235 }
3236
3237 /*!
3238  * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
3239  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3240  */
3241 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3242                                                                                  _nodal_connec(0),_nodal_connec_index(0),
3243                                                                                 _types(other._types)
3244 {
3245   if(other._nodal_connec)
3246     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3247   if(other._nodal_connec_index)
3248     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3249 }
3250
3251 MEDCouplingUMesh::~MEDCouplingUMesh()
3252 {
3253   if(_nodal_connec)
3254     _nodal_connec->decrRef();
3255   if(_nodal_connec_index)
3256     _nodal_connec_index->decrRef();
3257 }
3258
3259 /*!
3260  * Recomputes a set of cell types of \a this mesh. For more info see
3261  * \ref MEDCouplingUMeshNodalConnectivity.
3262  */
3263 void MEDCouplingUMesh::computeTypes()
3264 {
3265   if(_nodal_connec && _nodal_connec_index)
3266     {
3267       _types.clear();
3268       const int *conn=_nodal_connec->getConstPointer();
3269       const int *connIndex=_nodal_connec_index->getConstPointer();
3270       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3271       if (nbOfElem > 0)
3272         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3273           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3274     }
3275 }
3276
3277 /*!
3278  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3279  */
3280 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3281 {
3282   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3283     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3284 }
3285
3286 /*!
3287  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3288  */
3289 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3290 {
3291   if(!_nodal_connec_index || !_nodal_connec)
3292     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3293 }
3294
3295 /*!
3296  * Returns a number of cells constituting \a this mesh. 
3297  *  \return int - the number of cells in \a this mesh.
3298  *  \throw If the nodal connectivity of cells is not defined.
3299  */
3300 int MEDCouplingUMesh::getNumberOfCells() const
3301
3302   if(_nodal_connec_index)
3303     return _nodal_connec_index->getNumberOfTuples()-1;
3304   else
3305     if(_mesh_dim==-1)
3306       return 1;
3307     else
3308       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3309 }
3310
3311 /*!
3312  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3313  * mesh. For more info see \ref MEDCouplingMeshesPage.
3314  *  \return int - the dimension of \a this mesh.
3315  *  \throw If the mesh dimension is not defined using setMeshDimension().
3316  */
3317 int MEDCouplingUMesh::getMeshDimension() const
3318 {
3319   if(_mesh_dim<-1)
3320     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3321   return _mesh_dim;
3322 }
3323
3324 /*!
3325  * Returns a length of the nodal connectivity array.
3326  * This method is for test reason. Normally the integer returned is not useable by
3327  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3328  *  \return int - the length of the nodal connectivity array.
3329  */
3330 int MEDCouplingUMesh::getMeshLength() const
3331 {
3332   return _nodal_connec->getNbOfElems();
3333 }
3334
3335 /*!
3336  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3337  */
3338 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3339 {
3340   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3341   tinyInfo.push_back(getMeshDimension());
3342   tinyInfo.push_back(getNumberOfCells());
3343   if(_nodal_connec)
3344     tinyInfo.push_back(getMeshLength());
3345   else
3346     tinyInfo.push_back(-1);
3347 }
3348
3349 /*!
3350  * First step of unserialization process.
3351  */
3352 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3353 {
3354   return tinyInfo[6]<=0;
3355 }
3356
3357 /*!
3358  * Second step of serialization process.
3359  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3360  */
3361 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3362 {
3363   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3364   if(tinyInfo[5]!=-1)
3365     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3366 }
3367
3368 /*!
3369  * Third and final step of serialization process.
3370  */
3371 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3372 {
3373   MEDCouplingPointSet::serialize(a1,a2);
3374   if(getMeshDimension()>-1)
3375     {
3376       a1=DataArrayInt::New();
3377       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3378       int *ptA1=a1->getPointer();
3379       const int *conn=getNodalConnectivity()->getConstPointer();
3380       const int *index=getNodalConnectivityIndex()->getConstPointer();
3381       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3382       std::copy(conn,conn+getMeshLength(),ptA1);
3383     }
3384   else
3385     a1=0;
3386 }
3387
3388 /*!
3389  * Second and final unserialization process.
3390  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3391  */
3392 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3393 {
3394   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3395   setMeshDimension(tinyInfo[5]);
3396   if(tinyInfo[7]!=-1)
3397     {
3398       // Connectivity
3399       const int *recvBuffer=a1->getConstPointer();
3400       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3401       myConnecIndex->alloc(tinyInfo[6]+1,1);
3402       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3403       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3404       myConnec->alloc(tinyInfo[7],1);
3405       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3406       setConnectivity(myConnec, myConnecIndex);
3407     }
3408 }
3409
3410 /*!
3411  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3412  * CellIds are given using range specified by a start an end and step.
3413  */
3414 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3415 {
3416   checkFullyDefined();
3417   int ncell=getNumberOfCells();
3418   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3419   ret->_mesh_dim=_mesh_dim;
3420   ret->setCoords(_coords);
3421   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3422   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3423   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3424   int work=start;
3425   const int *conn=_nodal_connec->getConstPointer();
3426   const int *connIndex=_nodal_connec_index->getConstPointer();
3427   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3428     {
3429       if(work>=0 && work<ncell)
3430         {
3431           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3432         }
3433       else
3434         {
3435           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3436           throw INTERP_KERNEL::Exception(oss.str().c_str());
3437         }
3438     }
3439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3440   int *newConnPtr=newConn->getPointer();
3441   std::set<INTERP_KERNEL::NormalizedCellType> types;
3442   work=start;
3443   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3444     {
3445       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3446       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3447     }
3448   ret->setConnectivity(newConn,newConnI,false);
3449   ret->_types=types;
3450   ret->copyTinyInfoFrom(this);
3451   return ret.retn();
3452 }
3453
3454 /*!
3455  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3456  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3457  * The return newly allocated mesh will share the same coordinates as 'this'.
3458  */
3459 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3460 {
3461   checkFullyDefined();
3462   int ncell=getNumberOfCells();
3463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3464   ret->_mesh_dim=_mesh_dim;
3465   ret->setCoords(_coords);
3466   std::size_t nbOfElemsRet=std::distance(begin,end);
3467   int *connIndexRet=new int[nbOfElemsRet+1];
3468   connIndexRet[0]=0;
3469   const int *conn=_nodal_connec->getConstPointer();
3470   const int *connIndex=_nodal_connec_index->getConstPointer();
3471   int newNbring=0;
3472   for(const int *work=begin;work!=end;work++,newNbring++)
3473     {
3474       if(*work>=0 && *work<ncell)
3475         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3476       else
3477         {
3478           delete [] connIndexRet;
3479           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3480           throw INTERP_KERNEL::Exception(oss.str().c_str());
3481         }
3482     }
3483   int *connRet=new int[connIndexRet[nbOfElemsRet]];
3484   int *connRetWork=connRet;
3485   std::set<INTERP_KERNEL::NormalizedCellType> types;
3486   for(const int *work=begin;work!=end;work++)
3487     {
3488       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3489       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3490     }
3491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3492   connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3493   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3494   connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3495   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3496   ret->_types=types;
3497   ret->copyTinyInfoFrom(this);
3498   return ret.retn();
3499 }
3500
3501 /*!
3502  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3503  * mesh.<br>
3504  * For 1D cells, the returned field contains lengths.<br>
3505  * For 2D cells, the returned field contains areas.<br>
3506  * For 3D cells, the returned field contains volumes.
3507  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3508  *         orientation, i.e. the volume is always positive.
3509  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3510  *         and one time . The caller is to delete this field using decrRef() as it is no
3511  *         more needed.
3512  */
3513 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3514 {
3515   std::string name="MeasureOfMesh_";
3516   name+=getName();
3517   int nbelem=getNumberOfCells();
3518   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3519   field->setName(name.c_str());
3520   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3521   array->alloc(nbelem,1);
3522   double *area_vol=array->getPointer();
3523   field->setArray(array) ; array=0;
3524   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3525   field->synchronizeTimeWithMesh();
3526   if(getMeshDimension()!=-1)
3527     {
3528       int ipt;
3529       INTERP_KERNEL::NormalizedCellType type;
3530       int dim_space=getSpaceDimension();
3531       const double *coords=getCoords()->getConstPointer();
3532       const int *connec=getNodalConnectivity()->getConstPointer();
3533       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3534       for(int iel=0;iel<nbelem;iel++)
3535         {
3536           ipt=connec_index[iel];
3537           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3538           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);
3539         }
3540       if(isAbs)
3541         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3542     }
3543   else
3544     {
3545       area_vol[0]=std::numeric_limits<double>::max();
3546     }
3547   return field.retn();
3548 }
3549
3550 /*!
3551  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3552  * mesh.<br>
3553  * For 1D cells, the returned array contains lengths.<br>
3554  * For 2D cells, the returned array contains areas.<br>
3555  * For 3D cells, the returned array contains volumes.
3556  * This method avoids building explicitly a part of \a this mesh to perform the work.
3557  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3558  *         orientation, i.e. the volume is always positive.
3559  *  \param [in] begin - an array of cell ids of interest.
3560  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3561  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3562  *          delete this array using decrRef() as it is no more needed.
3563  * 
3564  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3565  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3566  *  \sa getMeasureField()
3567  */
3568 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3569 {
3570   std::string name="PartMeasureOfMesh_";
3571   name+=getName();
3572   int nbelem=(int)std::distance(begin,end);
3573   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3574   array->setName(name.c_str());
3575   array->alloc(nbelem,1);
3576   double *area_vol=array->getPointer();
3577   if(getMeshDimension()!=-1)
3578     {
3579       int ipt;
3580       INTERP_KERNEL::NormalizedCellType type;
3581       int dim_space=getSpaceDimension();
3582       const double *coords=getCoords()->getConstPointer();
3583       const int *connec=getNodalConnectivity()->getConstPointer();
3584       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3585       for(const int *iel=begin;iel!=end;iel++)
3586         {
3587           ipt=connec_index[*iel];
3588           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3589           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3590         }
3591       if(isAbs)
3592         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3593     }
3594   else
3595     {
3596       area_vol[0]=std::numeric_limits<double>::max();
3597     }
3598   return array.retn();
3599 }
3600
3601 /*!
3602  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3603  * \a this one. The returned field contains the dual cell volume for each corresponding
3604  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3605  *  the dual mesh in P1 sens of \a this.<br>
3606  * For 1D cells, the returned field contains lengths.<br>
3607  * For 2D cells, the returned field contains areas.<br>
3608  * For 3D cells, the returned field contains volumes.
3609  * This method is useful to check "P1*" conservative interpolators.
3610  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3611  *         orientation, i.e. the volume is always positive.
3612  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3613  *          nodes and one time. The caller is to delete this array using decrRef() as
3614  *          it is no more needed.
3615  */
3616 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3617 {
3618   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3619   std::string name="MeasureOnNodeOfMesh_";
3620   name+=getName();
3621   int nbNodes=getNumberOfNodes();
3622   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3623   double cst=1./((double)getMeshDimension()+1.);
3624   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3625   array->alloc(nbNodes,1);
3626   double *valsToFill=array->getPointer();
3627   std::fill(valsToFill,valsToFill+nbNodes,0.);
3628   const double *values=tmp->getArray()->getConstPointer();
3629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3631   getReverseNodalConnectivity(da,daInd);
3632   const int *daPtr=da->getConstPointer();
3633   const int *daIPtr=daInd->getConstPointer();
3634   for(int i=0;i<nbNodes;i++)
3635     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3636       valsToFill[i]+=cst*values[*cell];
3637   ret->setMesh(this);
3638   ret->setArray(array);
3639   return ret.retn();
3640 }
3641
3642 /*!
3643  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3644  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3645  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3646  * and are normalized.
3647  * <br> \a this can be either 
3648  * - a  2D mesh in 2D or 3D space or 
3649  * - an 1D mesh in 2D space.
3650  * 
3651  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3652  *          cells and one time. The caller is to delete this field using decrRef() as
3653  *          it is no more needed.
3654  *  \throw If the nodal connectivity of cells is not defined.
3655  *  \throw If the coordinates array is not set.
3656  *  \throw If the mesh dimension is not set.
3657  *  \throw If the mesh and space dimension is not as specified above.
3658  */
3659 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3660 {
3661   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3662     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3663   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3664   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3665   int nbOfCells=getNumberOfCells();
3666   int nbComp=getMeshDimension()+1;
3667   array->alloc(nbOfCells,nbComp);
3668   double *vals=array->getPointer();
3669   const int *connI=_nodal_connec_index->getConstPointer();
3670   const int *conn=_nodal_connec->getConstPointer();
3671   const double *coords=_coords->getConstPointer();
3672   if(getMeshDimension()==2)
3673     {
3674       if(getSpaceDimension()==3)
3675         {
3676           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3677           const double *locPtr=loc->getConstPointer();
3678           for(int i=0;i<nbOfCells;i++,vals+=3)
3679             {
3680               int offset=connI[i];
3681               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3682               double n=INTERP_KERNEL::norm<3>(vals);
3683               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3684             }
3685         }
3686       else
3687         {
3688           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3689           const double *isAbsPtr=isAbs->getArray()->begin();
3690           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3691             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3692         }
3693     }
3694   else//meshdimension==1
3695     {
3696       double tmp[2];
3697       for(int i=0;i<nbOfCells;i++)
3698         {
3699           int offset=connI[i];
3700           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3701           double n=INTERP_KERNEL::norm<2>(tmp);
3702           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3703           *vals++=-tmp[1];
3704           *vals++=tmp[0];
3705         }
3706     }
3707   ret->setArray(array);
3708   ret->setMesh(this);
3709   ret->synchronizeTimeWithSupport();
3710   return ret.retn();
3711 }
3712
3713 /*!
3714  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3715  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3716  * and are normalized.
3717  * <br> \a this can be either 
3718  * - a  2D mesh in 2D or 3D space or 
3719  * - an 1D mesh in 2D space.
3720  * 
3721  * This method avoids building explicitly a part of \a this mesh to perform the work.
3722  *  \param [in] begin - an array of cell ids of interest.
3723  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3724  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3725  *          cells and one time. The caller is to delete this field using decrRef() as
3726  *          it is no more needed.
3727  *  \throw If the nodal connectivity of cells is not defined.
3728  *  \throw If the coordinates array is not set.
3729  *  \throw If the mesh dimension is not set.
3730  *  \throw If the mesh and space dimension is not as specified above.
3731  *  \sa buildOrthogonalField()
3732  *
3733  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3734  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3735  */
3736 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3737 {
3738   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3739     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3740   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3741   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3742   std::size_t nbelems=std::distance(begin,end);
3743   int nbComp=getMeshDimension()+1;
3744   array->alloc((int)nbelems,nbComp);
3745   double *vals=array->getPointer();
3746   const int *connI=_nodal_connec_index->getConstPointer();
3747   const int *conn=_nodal_connec->getConstPointer();
3748   const double *coords=_coords->getConstPointer();
3749   if(getMeshDimension()==2)
3750     {
3751       if(getSpaceDimension()==3)
3752         {
3753           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3754           const double *locPtr=loc->getConstPointer();
3755           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3756             {
3757               int offset=connI[*i];
3758               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3759               double n=INTERP_KERNEL::norm<3>(vals);
3760               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3761             }
3762         }
3763       else
3764         {
3765           for(std::size_t i=0;i<nbelems;i++)
3766             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3767         }
3768     }
3769   else//meshdimension==1
3770     {
3771       double tmp[2];
3772       for(const int *i=begin;i!=end;i++)
3773         {
3774           int offset=connI[*i];
3775           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3776           double n=INTERP_KERNEL::norm<2>(tmp);
3777           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3778           *vals++=-tmp[1];
3779           *vals++=tmp[0];
3780         }
3781     }
3782   ret->setArray(array);
3783   ret->setMesh(this);
3784   ret->synchronizeTimeWithSupport();
3785   return ret.retn();
3786 }
3787
3788 /*!
3789  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3790  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3791  * and are \b not normalized.
3792  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3793  *          cells and one time. The caller is to delete this field using decrRef() as
3794  *          it is no more needed.
3795  *  \throw If the nodal connectivity of cells is not defined.
3796  *  \throw If the coordinates array is not set.
3797  *  \throw If \a this->getMeshDimension() != 1.
3798  *  \throw If \a this mesh includes cells of type other than SEG2.
3799  */
3800 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3801 {
3802    if(getMeshDimension()!=1)
3803     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3804    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3805      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3806    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3807    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3808    int nbOfCells=getNumberOfCells();
3809    int spaceDim=getSpaceDimension();
3810    array->alloc(nbOfCells,spaceDim);
3811    double *pt=array->getPointer();
3812    const double *coo=getCoords()->getConstPointer();
3813    std::vector<int> conn;
3814    conn.reserve(2);
3815    for(int i=0;i<nbOfCells;i++)
3816      {
3817        conn.resize(0);
3818        getNodeIdsOfCell(i,conn);
3819        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3820      }
3821    ret->setArray(array);
3822    ret->setMesh(this);
3823    ret->synchronizeTimeWithSupport();
3824    return ret.retn();   
3825 }
3826
3827 /*!
3828  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3829  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3830  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3831  * from. If a result face is shared by two 3D cells, then the face in included twice in
3832  * the result mesh.
3833  *  \param [in] origin - 3 components of a point defining location of the plane.
3834  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3835  *         must be greater than 1e-6.
3836  *  \param [in] eps - half-thickness of the plane.
3837  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3838  *         producing correspondent 2D cells. The caller is to delete this array
3839  *         using decrRef() as it is no more needed.
3840  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3841  *         not share the node coordinates array with \a this mesh. The caller is to
3842  *         delete this mesh using decrRef() as it is no more needed.  
3843  *  \throw If the coordinates array is not set.
3844  *  \throw If the nodal connectivity of cells is not defined.
3845  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3846  *  \throw If magnitude of \a vec is less than 1e-6.
3847  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3848  *  \throw If \a this includes quadratic cells.
3849  */
3850 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3851 {
3852   checkFullyDefined();
3853   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3856   if(candidates->empty())
3857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3858   std::vector<int> nodes;
3859   DataArrayInt *cellIds1D=0;
3860   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3861   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3866   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3867   revDesc2=0; revDescIndx2=0;
3868   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3869   revDesc1=0; revDescIndx1=0;
3870   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3872   //
3873   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3874   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3875     cut3DCurve[*it]=-1;
3876   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3877   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3878   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3879                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3880                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3882   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3883   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3884   if(cellIds2->empty())
3885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3886   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3887   ret->setCoords(mDesc1->getCoords());
3888   ret->setConnectivity(conn,connI,true);
3889   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3890   return ret.retn();
3891 }
3892
3893 /*!
3894  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3895 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
3896 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3897 the result mesh.
3898  *  \param [in] origin - 3 components of a point defining location of the plane.
3899  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3900  *         must be greater than 1e-6.
3901  *  \param [in] eps - half-thickness of the plane.
3902  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3903  *         producing correspondent segments. The caller is to delete this array
3904  *         using decrRef() as it is no more needed.
3905  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3906  *         mesh in 3D space. This mesh does not share the node coordinates array with
3907  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3908  *         no more needed. 
3909  *  \throw If the coordinates array is not set.
3910  *  \throw If the nodal connectivity of cells is not defined.
3911  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3912  *  \throw If magnitude of \a vec is less than 1e-6.
3913  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3914  *  \throw If \a this includes quadratic cells.
3915  */
3916 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3917 {
3918   checkFullyDefined();
3919   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3920     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3922   if(candidates->empty())
3923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3924   std::vector<int> nodes;
3925   DataArrayInt *cellIds1D=0;
3926   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3927   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3930   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3931   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3932   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3933   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3934   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3935   //
3936   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3937   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3938     cut3DCurve[*it]=-1;
3939   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3940   int ncellsSub=subMesh->getNumberOfCells();
3941   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3942   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3943                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3944                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3945   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3946   conn->alloc(0,1);
3947   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3948   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3949   for(int i=0;i<ncellsSub;i++)
3950     {
3951       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3952         {
3953           if(cut3DSurf[i].first!=-2)
3954             {
3955               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3956               connI->pushBackSilent(conn->getNumberOfTuples());
3957               cellIds2->pushBackSilent(i);
3958             }
3959           else
3960             {
3961               int cellId3DSurf=cut3DSurf[i].second;
3962               int offset=nodalI[cellId3DSurf]+1;
3963               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3964               for(int j=0;j<nbOfEdges;j++)
3965                 {
3966                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3967                   connI->pushBackSilent(conn->getNumberOfTuples());
3968                   cellIds2->pushBackSilent(cellId3DSurf);
3969                 }
3970             }
3971         }
3972     }
3973   if(cellIds2->empty())
3974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3975   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3976   ret->setCoords(mDesc1->getCoords());
3977   ret->setConnectivity(conn,connI,true);
3978   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3979   return ret.retn();
3980 }
3981
3982 /*!
3983  * Finds cells whose bounding boxes intersect a given plane.
3984  *  \param [in] origin - 3 components of a point defining location of the plane.
3985  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3986  *         must be greater than 1e-6.
3987  *  \param [in] eps - half-thickness of the plane.
3988  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3989  *         cells. The caller is to delete this array using decrRef() as it is no more
3990  *         needed.
3991  *  \throw If the coordinates array is not set.
3992  *  \throw If the nodal connectivity of cells is not defined.
3993  *  \throw If \a this->getSpaceDimension() != 3.
3994  *  \throw If magnitude of \a vec is less than 1e-6.
3995  *  \sa buildSlice3D()
3996  */
3997 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3998 {
3999   checkFullyDefined();
4000   if(getSpaceDimension()!=3)
4001     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4002   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4003   if(normm<1e-6)
4004     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4005   double vec2[3];
4006   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4007   double angle=acos(vec[2]/normm);
4008   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
4009   double bbox[6];
4010   if(angle>eps)
4011     {
4012       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
4013       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
4014       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4015       mw->setCoords(coo);
4016       mw->getBoundingBox(bbox);
4017       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4018       cellIds=mw->getCellsInBoundingBox(bbox,eps);
4019     }
4020   else
4021     {
4022       getBoundingBox(bbox);
4023       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4024       cellIds=getCellsInBoundingBox(bbox,eps);
4025     }
4026   return cellIds.retn();
4027 }
4028
4029 /*!
4030  * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4031  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4032  * No consideration of coordinate is done by this method.
4033  * 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)
4034  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
4035  */
4036 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
4037 {
4038   if(getMeshDimension()!=1)
4039     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4040   int nbCells=getNumberOfCells();
4041   if(nbCells<1)
4042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4043   const int *connI=_nodal_connec_index->getConstPointer();
4044   const int *conn=_nodal_connec->getConstPointer();
4045   int ref=conn[connI[0]+2];
4046   for(int i=1;i<nbCells;i++)
4047     {
4048       if(conn[connI[i]+1]!=ref)
4049         return false;
4050       ref=conn[connI[i]+2];
4051     }
4052   return true;
4053 }
4054
4055 /*!
4056  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4057  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4058  * @param pt reference point of the line
4059  * @param v normalized director vector of the line
4060  * @param eps max precision before throwing an exception
4061  * @param res output of size this->getNumberOfCells
4062  */
4063 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4064 {
4065   if(getMeshDimension()!=1)
4066     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4067    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4068      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4069    if(getSpaceDimension()!=3)
4070      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4071    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4072    const double *fPtr=f->getArray()->getConstPointer();
4073    double tmp[3];
4074    for(int i=0;i<getNumberOfCells();i++)
4075      {
4076        const double *tmp1=fPtr+3*i;
4077        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4078        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4079        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4080        double n1=INTERP_KERNEL::norm<3>(tmp);
4081        n1/=INTERP_KERNEL::norm<3>(tmp1);
4082        if(n1>eps)
4083          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4084      }
4085    const double *coo=getCoords()->getConstPointer();
4086    for(int i=0;i<getNumberOfNodes();i++)
4087      {
4088        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4089        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4090        res[i]=std::accumulate(tmp,tmp+3,0.);
4091      }
4092 }
4093
4094 /*!
4095  * 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. 
4096  * \a this is expected to be a mesh so that its space dimension is equal to its
4097  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4098  * 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).
4099  * 
4100  * 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 
4101  * 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
4102  * to the node that minimizes distance with the input point then -1 is returned in cellId.
4103  *
4104  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4105  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4106  *
4107  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4108  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4109  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4110  * \return the positive value of the distance.
4111  * \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
4112  * dimension - 1.
4113  * \sa DataArrayDouble::distanceToTuple
4114  */
4115 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
4116 {
4117   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4118   if(meshDim!=spaceDim-1)
4119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4120   if(meshDim!=2 && meshDim!=1)
4121     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4122   checkFullyDefined();
4123   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4124     { 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()); }
4125   nodeId=-1;
4126   double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
4127   if(nodeId==-1)
4128     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
4129   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
4130   switch(meshDim)
4131     {
4132     case 2:
4133       {
4134         distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
4135         return ret0;
4136       }
4137     case 1:
4138       {
4139         distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
4140         return ret0;
4141       }
4142     default:
4143       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4144     }
4145   
4146   return ret0;
4147 }
4148
4149
4150 /*!
4151  * \param [in] pt the start pointer (included) of the coordinates of the point
4152  * \param [in] cellIds
4153  * \param [in,out] ret0 the min distance between \a this and the external input point
4154  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4155  * \sa MEDCouplingUMesh::distanceToPoint
4156  */
4157 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4158 {
4159   const double *coords=_coords->getConstPointer();
4160   cellId=-1; 
4161   if(cellIds->empty())
4162     return;
4163   const int *ptr=_nodal_connec->getConstPointer();
4164   const int *ptrI=_nodal_connec_index->getConstPointer();
4165   for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4166     {
4167       switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4168         {
4169         case INTERP_KERNEL::NORM_TRI3:
4170           {
4171             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
4172             if(tmp<ret0)
4173               { ret0=tmp; cellId=*zeCell; }
4174             break;
4175           }
4176         case INTERP_KERNEL::NORM_QUAD4:
4177         case INTERP_KERNEL::NORM_POLYGON:
4178           {
4179             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
4180             if(tmp<ret0)
4181               { ret0=tmp; cellId=*zeCell; }
4182             break;
4183           }
4184         default:
4185           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4186         }
4187     }
4188 }
4189
4190 /*!
4191  * \param [in] pt the start pointer (included) of the coordinates of the point
4192  * \param [in] cellIds
4193  * \param [in,out] ret0 the min distance between \a this and the external input point
4194  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4195  * \sa MEDCouplingUMesh::distanceToPoint
4196  */
4197 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
4198 {
4199   const double *coords=_coords->getConstPointer();
4200   if(cellIds->empty())
4201     { cellId=-1; return; }
4202   const int *ptr=_nodal_connec->getConstPointer();
4203   const int *ptrI=_nodal_connec_index->getConstPointer();
4204   for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
4205     {
4206        switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
4207         {
4208         case INTERP_KERNEL::NORM_SEG2:
4209           {
4210             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
4211             if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
4212             if(tmp<ret0)
4213               { ret0=tmp; cellId=*zeCell; }
4214             break;
4215           }
4216         default:
4217           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4218         }
4219     }
4220 }
4221
4222 /*!
4223  * Finds cells in contact with a ball (i.e. a point with precision). 
4224  * \warning This method is suitable if the caller intends to evaluate only one
4225  *          point, for more points getCellsContainingPoints() is recommended as it is
4226  *          faster. 
4227  *  \param [in] pos - array of coordinates of the ball central point.
4228  *  \param [in] eps - ball radius.
4229  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4230  *         if there are no such cells.
4231  *  \throw If the coordinates array is not set.
4232  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4233  */
4234 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4235 {
4236   std::vector<int> elts;
4237   getCellsContainingPoint(pos,eps,elts);
4238   if(elts.empty())
4239     return -1;
4240   return elts.front();
4241 }
4242
4243 /*!
4244  * Finds cells in contact with a ball (i.e. a point with precision).
4245  * \warning This method is suitable if the caller intends to evaluate only one
4246  *          point, for more points getCellsContainingPoints() is recommended as it is
4247  *          faster. 
4248  *  \param [in] pos - array of coordinates of the ball central point.
4249  *  \param [in] eps - ball radius.
4250  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4251  *         before inserting ids.
4252  *  \throw If the coordinates array is not set.
4253  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4254  *
4255  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4256  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4257  */
4258 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4259 {
4260   std::vector<int> eltsIndex;
4261   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4262 }
4263
4264 /// @cond INTERNAL
4265
4266 namespace ParaMEDMEM
4267 {
4268   template<const int SPACEDIMM>
4269   class DummyClsMCUG
4270   {
4271   public:
4272     static const int MY_SPACEDIM=SPACEDIMM;
4273     static const int MY_MESHDIM=8;
4274     typedef int MyConnType;
4275     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4276     // begin
4277     // useless, but for windows compilation ...
4278     const double* getCoordinatesPtr() const { return 0; }
4279     const int* getConnectivityPtr() const { return 0; }
4280     const int* getConnectivityIndexPtr() const { return 0; }
4281     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4282     // end
4283   };
4284
4285   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4286   {
4287     INTERP_KERNEL::Edge *ret=0;
4288     switch(typ)
4289       {
4290       case INTERP_KERNEL::NORM_SEG2:
4291         {
4292           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4293           break;
4294         }
4295       case INTERP_KERNEL::NORM_SEG3:
4296         {
4297           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4298           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4299           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4300           bool colinearity=inters.areColinears();
4301           delete e1; delete e2;
4302           if(colinearity)
4303             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4304           else
4305             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4306           mapp2[bg[2]].second=false;
4307           break;
4308         }
4309       default:
4310         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4311       }
4312     return ret;
4313   }
4314
4315   /*!
4316    * 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'.
4317    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4318    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4319    */
4320   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4321   {
4322     mapp.clear();
4323     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.
4324     const double *coo=mDesc->getCoords()->getConstPointer();
4325     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4326     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4327     std::set<int> s;
4328     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4329       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4330     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4331       {
4332         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4333         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4334       }
4335     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4336     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4337       {
4338         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4339         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4340       }
4341     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4342       {
4343         if((*it2).second.second)
4344           mapp[(*it2).second.first]=(*it2).first;
4345         ((*it2).second.first)->decrRef();
4346       }
4347     return ret;
4348   }
4349
4350   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4351   {
4352     if(nodeId>=offset2)
4353       {
4354         int locId=nodeId-offset2;
4355         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4356       }
4357     if(nodeId>=offset1)
4358       {
4359         int locId=nodeId-offset1;
4360         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4361       }
4362     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4363   }
4364
4365   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4366                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4367                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4368   {
4369     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4370       {
4371         int eltId1=abs(*desc1)-1;
4372         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4373           {
4374             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4375             if(it==mappRev.end())
4376               {
4377                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4378                 mapp[node]=*it1;
4379                 mappRev[*it1]=node;
4380               }
4381           }
4382       }
4383   }
4384 }
4385
4386 /// @endcond
4387
4388 template<int SPACEDIM>
4389 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4390                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4391 {
4392   std::vector<double> bbox;
4393   eltsIndex.resize(nbOfPoints+1);
4394   eltsIndex[0]=0;
4395   elts.clear();
4396   getBoundingBoxForBBTree(bbox);
4397   int nbOfCells=getNumberOfCells();
4398   const int *conn=_nodal_connec->getConstPointer();
4399   const int *connI=_nodal_connec_index->getConstPointer();
4400   double bb[2*SPACEDIM];
4401   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4402   for(int i=0;i<nbOfPoints;i++)
4403     {
4404       eltsIndex[i+1]=eltsIndex[i];
4405       for(int j=0;j<SPACEDIM;j++)
4406         {
4407           bb[2*j]=pos[SPACEDIM*i+j];
4408           bb[2*j+1]=pos[SPACEDIM*i+j];
4409         }
4410       std::vector<int> candidates;
4411       myTree.getIntersectingElems(bb,candidates);
4412       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4413         {
4414           int sz=connI[(*iter)+1]-connI[*iter]-1;
4415           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4416                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4417                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4418             {
4419               eltsIndex[i+1]++;
4420               elts.push_back(*iter);
4421             }
4422         }
4423     }
4424 }
4425 /*!
4426  * Finds cells in contact with several balls (i.e. points with precision).
4427  * This method is an extension of getCellContainingPoint() and
4428  * getCellsContainingPoint() for the case of multiple points.
4429  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4430  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4431  *         this->getSpaceDimension() * \a nbOfPoints 
4432  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4433  *  \param [in] eps - radius of balls (i.e. the precision).
4434  *  \param [in,out] elts - vector returning ids of found cells.
4435  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4436  *         dividing cell ids in \a elts into groups each referring to one
4437  *         point. Its every element (except the last one) is an index pointing to the
4438  *         first id of a group of cells. For example cells in contact with the *i*-th
4439  *         point are described by following range of indices:
4440  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4441  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4442  *         Number of cells in contact with the *i*-th point is
4443  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4444  *  \throw If the coordinates array is not set.
4445  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4446  *
4447  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4448  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4449  */
4450 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4451                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4452 {
4453   int spaceDim=getSpaceDimension();
4454   int mDim=getMeshDimension();
4455   if(spaceDim==3)
4456     {
4457       if(mDim==3)
4458         {
4459           const double *coords=_coords->getConstPointer();
4460           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4461         }
4462       /*else if(mDim==2)
4463         {
4464           
4465         }*/
4466       else
4467         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4468     }
4469   else if(spaceDim==2)
4470     {
4471       if(mDim==2)
4472         {
4473           const double *coords=_coords->getConstPointer();
4474           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4475         }
4476       else
4477         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4478     }
4479   else if(spaceDim==1)
4480     {
4481       if(mDim==1)
4482         {
4483           const double *coords=_coords->getConstPointer();
4484           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4485         }
4486       else
4487         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4488     }
4489   else
4490     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4491 }
4492
4493 /*!
4494  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4495  * least two its edges intersect each other anywhere except their extremities. An
4496  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4497  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4498  *         cleared before filling in.
4499  *  \param [in] eps - precision.
4500  *  \throw If \a this->getMeshDimension() != 2.
4501  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4502  */
4503 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4504 {
4505   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4506   if(getMeshDimension()!=2)
4507     throw INTERP_KERNEL::Exception(msg);
4508   int spaceDim=getSpaceDimension();
4509   if(spaceDim!=2 && spaceDim!=3)
4510     throw INTERP_KERNEL::Exception(msg);
4511   const int *conn=_nodal_connec->getConstPointer();
4512   const int *connI=_nodal_connec_index->getConstPointer();
4513   int nbOfCells=getNumberOfCells();
4514   std::vector<double> cell2DinS2;
4515   for(int i=0;i<nbOfCells;i++)
4516     {
4517       int offset=connI[i];
4518       int nbOfNodesForCell=connI[i+1]-offset-1;
4519       if(nbOfNodesForCell<=3)
4520         continue;
4521       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4522       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4523       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4524         cells.push_back(i);
4525       cell2DinS2.clear();
4526     }
4527 }
4528
4529 /*!
4530  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4531  *
4532  * 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.
4533  * 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.
4534  * 
4535  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4536  * This convex envelop is computed using Jarvis march algorithm.
4537  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4538  * 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)
4539  * 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.
4540  *
4541  * @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.
4542  */
4543 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4544 {
4545   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4546     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4547   checkFullyDefined();
4548   const double *coords=getCoords()->getConstPointer();
4549   int nbOfCells=getNumberOfCells();
4550   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4551   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4552   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4553   int *workIndexOut=nodalConnecIndexOut->getPointer();
4554   *workIndexOut=0;
4555   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4556   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4557   std::set<INTERP_KERNEL::NormalizedCellType> types;
4558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4559   isChanged->alloc(0,1);
4560   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4561     {
4562       int pos=nodalConnecOut->getNumberOfTuples();
4563       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4564         isChanged->pushBackSilent(i);
4565       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4566       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4567     }
4568   if(isChanged->empty())
4569     return 0;
4570   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4571   _types=types;
4572   return isChanged.retn();
4573 }
4574
4575 /*!
4576  * This method is \b NOT const because it can modify 'this'.
4577  * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4578  * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4579  * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4580  * \b 1 for translation and rotation around point of 'mesh1D'.
4581  * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.  
4582  */
4583 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4584 {
4585   checkFullyDefined();
4586   mesh1D->checkFullyDefined();
4587   if(!mesh1D->isContiguous1D())
4588     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4589   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4590     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4591   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4592     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4593   if(mesh1D->getMeshDimension()!=1)
4594     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4595   bool isQuad=false;
4596   if(isPresenceOfQuadratic())
4597     {
4598       if(mesh1D->isFullyQuadratic())
4599         isQuad=true;
4600       else
4601         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4602     }
4603   zipCoords();
4604   int oldNbOfNodes=getNumberOfNodes();
4605   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4606   switch(policy)
4607     {
4608     case 0:
4609       {
4610         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4611         break;
4612       }
4613     case 1:
4614       {
4615         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4616         break;
4617       }
4618     default:
4619       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4620     }
4621   setCoords(newCoords);
4622   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4623   updateTime();
4624   return ret.retn();
4625 }
4626
4627 /*!
4628  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4629  * If it is not the case an exception will be thrown.
4630  * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4631  * intersection of plane defined by ('origin','vec').
4632  * This method has one in/out parameter : 'cut3DCurve'.
4633  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4634  * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4635  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4636  * This method will throw an exception if 'this' contains a non linear segment.
4637  */
4638 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4639 {
4640   checkFullyDefined();
4641   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4642     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4643   int ncells=getNumberOfCells();
4644   int nnodes=getNumberOfNodes();
4645   double vec2[3],vec3[3],vec4[3];
4646   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4647   if(normm<1e-6)
4648     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4649   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4650   const int *conn=_nodal_connec->getConstPointer();
4651   const int *connI=_nodal_connec_index->getConstPointer();
4652   const double *coo=_coords->getConstPointer();
4653   std::vector<double> addCoo;
4654   for(int i=0;i<ncells;i++)
4655     {
4656       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4657         {
4658           if(cut3DCurve[i]==-2)
4659             {
4660               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4661               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];
4662               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4663               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4664               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4665                 {
4666                   const double *st2=coo+3*st;
4667                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4668                   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]));
4669                   if(pos>eps && pos<1-eps)
4670                     {
4671                       int nNode=((int)addCoo.size())/3;
4672                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4673                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4674                       cut3DCurve[i]=nnodes+nNode;
4675                     }
4676                 }
4677             }
4678         }
4679       else
4680         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4681     }
4682   if(!addCoo.empty())
4683     {
4684       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4685       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4686       coo2->alloc(newNbOfNodes,3);
4687       double *tmp=coo2->getPointer();
4688       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4689       std::copy(addCoo.begin(),addCoo.end(),tmp);
4690       DataArrayDouble::SetArrayIn(coo2,_coords);
4691     }
4692 }
4693
4694 /*!
4695  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4696  * @param mesh1D is the input 1D mesh used for translation computation.
4697  * @return newCoords new coords filled by this method. 
4698  */
4699 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4700 {
4701   int oldNbOfNodes=getNumberOfNodes();
4702   int nbOf1DCells=mesh1D->getNumberOfCells();
4703   int spaceDim=getSpaceDimension();
4704   DataArrayDouble *ret=DataArrayDouble::New();
4705   std::vector<bool> isQuads;
4706   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4707   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4708   double *retPtr=ret->getPointer();
4709   const double *coords=getCoords()->getConstPointer();
4710   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4711   std::vector<int> v;
4712   std::vector<double> c;
4713   double vec[3];
4714   v.reserve(3);
4715   c.reserve(6);
4716   for(int i=0;i<nbOf1DCells;i++)
4717     {
4718       v.resize(0);
4719       mesh1D->getNodeIdsOfCell(i,v);
4720       c.resize(0);
4721       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4722       mesh1D->getCoordinatesOfNode(v[0],c);
4723       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4724       for(int j=0;j<oldNbOfNodes;j++)
4725         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4726       if(isQuad)
4727         {
4728           c.resize(0);
4729           mesh1D->getCoordinatesOfNode(v[1],c);
4730           mesh1D->getCoordinatesOfNode(v[0],c);
4731           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4732           for(int j=0;j<oldNbOfNodes;j++)
4733             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4734         }
4735     }
4736   ret->copyStringInfoFrom(*getCoords());
4737   return ret;
4738 }
4739
4740 /*!
4741  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4742  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4743  * @return newCoords new coords filled by this method. 
4744  */
4745 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4746 {
4747   if(mesh1D->getSpaceDimension()==2)
4748     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4749   if(mesh1D->getSpaceDimension()==3)
4750     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4751   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4752 }
4753
4754 /*!
4755  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4756  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4757  * @return newCoords new coords filled by this method. 
4758  */
4759 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4760 {
4761   if(isQuad)
4762     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4763   int oldNbOfNodes=getNumberOfNodes();
4764   int nbOf1DCells=mesh1D->getNumberOfCells();
4765   if(nbOf1DCells<2)
4766     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4767   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4768   int nbOfLevsInVec=nbOf1DCells+1;
4769   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4770   double *retPtr=ret->getPointer();
4771   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4772   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4773   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4774   tmp->setCoords(tmp2);
4775   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4776   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4777   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4778   for(int i=1;i<nbOfLevsInVec;i++)
4779     {
4780       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4781       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4782       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4783       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4784       tmp->translate(vec);
4785       double tmp3[2],radius,alpha,alpha0;
4786       const double *p0=i+1<nbOfLevsInVec?begin:third;
4787       const double *p1=i+1<nbOfLevsInVec?end:begin;
4788       const double *p2=i+1<nbOfLevsInVec?third:end;
4789       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4790       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]);
4791       double angle=acos(cosangle/(radius*radius));
4792       tmp->rotate(end,0,angle);
4793       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4794     }
4795   return ret.retn();
4796 }
4797
4798 /*!
4799  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4800  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4801  * @return newCoords new coords filled by this method. 
4802  */
4803 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4804 {
4805   if(isQuad)
4806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4807   int oldNbOfNodes=getNumberOfNodes();
4808   int nbOf1DCells=mesh1D->getNumberOfCells();
4809   if(nbOf1DCells<2)
4810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4811   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4812   int nbOfLevsInVec=nbOf1DCells+1;
4813   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4814   double *retPtr=ret->getPointer();
4815   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4816   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4817   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4818   tmp->setCoords(tmp2);
4819   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4820   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4821   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4822   for(int i=1;i<nbOfLevsInVec;i++)
4823     {
4824       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4825       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4826       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4827       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4828       tmp->translate(vec);
4829       double tmp3[2],radius,alpha,alpha0;
4830       const double *p0=i+1<nbOfLevsInVec?begin:third;
4831       const double *p1=i+1<nbOfLevsInVec?end:begin;
4832       const double *p2=i+1<nbOfLevsInVec?third:end;
4833       double vecPlane[3]={
4834         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4835         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4836         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4837       };
4838       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4839       if(norm>1.e-7)
4840         {
4841           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4842           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4843           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4844           double s2=norm2;
4845           double c2=cos(asin(s2));
4846           double m[3][3]={
4847             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4848             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4849             {-vec2[1]*s2, vec2[0]*s2, c2}
4850           };
4851           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]};
4852           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]};
4853           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]};
4854           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4855           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]);
4856           double angle=acos(cosangle/(radius*radius));
4857           tmp->rotate(end,vecPlane,angle);
4858           
4859         }
4860       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4861     }
4862   return ret.retn();
4863 }
4864
4865 /*!
4866  * This method is private because not easy to use for end user. This method is const contrary to
4867  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4868  * the coords sorted slice by slice.
4869  * @param isQuad specifies presence of quadratic cells.
4870  */
4871 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4872 {
4873   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4874   int nbOf2DCells=getNumberOfCells();
4875   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4876   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4877   const int *conn=_nodal_connec->getConstPointer();
4878   const int *connI=_nodal_connec_index->getConstPointer();
4879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4881   newConnI->alloc(nbOf3DCells+1,1);
4882   int *newConnIPtr=newConnI->getPointer();
4883   *newConnIPtr++=0;
4884   std::vector<int> newc;
4885   for(int j=0;j<nbOf2DCells;j++)
4886     {
4887       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4888       *newConnIPtr++=(int)newc.size();
4889     }
4890   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4891   int *newConnPtr=newConn->getPointer();
4892   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4893   newConnIPtr=newConnI->getPointer();
4894   for(int iz=0;iz<nbOf1DCells;iz++)
4895     {
4896       if(iz!=0)
4897         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4898       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4899         {
4900           int icell=(int)(iter-newc.begin());
4901           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4902             {
4903               if(*iter!=-1)
4904                 *newConnPtr=(*iter)+iz*deltaPerLev;
4905               else
4906                 *newConnPtr=-1;
4907             }
4908           else
4909             *newConnPtr=(*iter);
4910         }
4911     }
4912   ret->setConnectivity(newConn,newConnI,true);
4913   ret->setCoords(getCoords());
4914   return ret;
4915 }
4916
4917 /*!
4918  * Checks if \a this mesh is constituted by only quadratic cells.
4919  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4920  *  \throw If the coordinates array is not set.
4921  *  \throw If the nodal connectivity of cells is not defined.
4922  */
4923 bool MEDCouplingUMesh::isFullyQuadratic() const
4924 {
4925   checkFullyDefined();
4926   bool ret=true;
4927   int nbOfCells=getNumberOfCells();
4928   for(int i=0;i<nbOfCells && ret;i++)
4929     {
4930       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4931       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4932       ret=cm.isQuadratic();
4933     }
4934   return ret;
4935 }
4936
4937 /*!
4938  * Checks if \a this mesh includes any quadratic cell.
4939  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4940  *  \throw If the coordinates array is not set.
4941  *  \throw If the nodal connectivity of cells is not defined.
4942  */
4943 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4944 {
4945   checkFullyDefined();
4946   bool ret=false;
4947   int nbOfCells=getNumberOfCells();
4948   for(int i=0;i<nbOfCells && !ret;i++)
4949     {
4950       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4951       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4952       ret=cm.isQuadratic();
4953     }
4954   return ret;
4955 }
4956
4957 /*!
4958  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4959  * this mesh, it remains unchanged.
4960  *  \throw If the coordinates array is not set.
4961  *  \throw If the nodal connectivity of cells is not defined.
4962  */
4963 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4964 {
4965   checkFullyDefined();
4966   int nbOfCells=getNumberOfCells();
4967   int delta=0;
4968   for(int i=0;i<nbOfCells;i++)
4969     {
4970       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4971       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4972       if(cm.isQuadratic())
4973         {
4974           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4975           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4976           delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4977         }
4978     }
4979   if(delta==0)
4980     return ;
4981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4983   newConn->alloc(getMeshLength()-delta,1);
4984   newConnI->alloc(nbOfCells+1,1);
4985   const int *icptr=_nodal_connec->getConstPointer();
4986   const int *iciptr=_nodal_connec_index->getConstPointer();
4987   int *ocptr=newConn->getPointer();
4988   int *ociptr=newConnI->getPointer();
4989   *ociptr=0;
4990   _types.clear();
4991   for(int i=0;i<nbOfCells;i++,ociptr++)
4992     {
4993       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4994       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4995       if(!cm.isQuadratic())
4996         {
4997           _types.insert(type);
4998           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4999           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5000         }
5001       else
5002         {
5003           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5004           _types.insert(typel);
5005           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5006           int newNbOfNodes=cml.getNumberOfNodes();
5007           *ocptr++=(int)typel;
5008           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5009           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5010         }
5011     }
5012   setConnectivity(newConn,newConnI,false);
5013 }
5014
5015 /*!
5016  * This method converts all linear cell in \a this to quadratic one.
5017  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5018  * 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)
5019  * 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.
5020  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5021  * end of the existing coordinates.
5022  * 
5023  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5024  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5025  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5026  * 
5027  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5028  *
5029  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5030  */
5031 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
5032 {
5033   DataArrayInt *conn=0,*connI=0;
5034   DataArrayDouble *coords=0;
5035   std::set<INTERP_KERNEL::NormalizedCellType> types;
5036   checkFullyDefined();
5037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5038   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5039   int meshDim=getMeshDimension();
5040   switch(conversionType)
5041     {
5042     case 0:
5043       switch(meshDim)
5044         {
5045         case 1:
5046           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5047           connSafe=conn; connISafe=connI; coordsSafe=coords;
5048           break;
5049         case 2:
5050           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5051           connSafe=conn; connISafe=connI; coordsSafe=coords;
5052           break;
5053         case 3:
5054           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5055           connSafe=conn; connISafe=connI; coordsSafe=coords;
5056           break;
5057         default:
5058           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5059         }
5060       break;
5061     case 1:
5062       {
5063         switch(meshDim)
5064         {
5065         case 1:
5066           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5067           connSafe=conn; connISafe=connI; coordsSafe=coords;
5068           break;
5069         case 2:
5070           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5071           connSafe=conn; connISafe=connI; coordsSafe=coords;
5072           break;
5073         case 3:
5074           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5075           connSafe=conn; connISafe=connI; coordsSafe=coords;
5076           break;
5077         default:
5078           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5079         }
5080         break;
5081       }
5082     default:
5083       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5084     }
5085   setConnectivity(connSafe,connISafe,false);
5086   _types=types;
5087   setCoords(coordsSafe);
5088   return ret.retn();
5089 }
5090
5091 /*!
5092  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5093  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5094  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5095  */
5096 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5097 {
5098   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5099   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5101   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5102   int nbOfCells=getNumberOfCells();
5103   int nbOfNodes=getNumberOfNodes();
5104   const int *cPtr=_nodal_connec->getConstPointer();
5105   const int *icPtr=_nodal_connec_index->getConstPointer();
5106   int lastVal=0,offset=nbOfNodes;
5107   for(int i=0;i<nbOfCells;i++,icPtr++)
5108     {
5109       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5110       if(type==INTERP_KERNEL::NORM_SEG2)
5111         {
5112           types.insert(INTERP_KERNEL::NORM_SEG3);
5113           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5114           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5115           newConn->pushBackSilent(offset++);
5116           lastVal+=4;
5117           newConnI->pushBackSilent(lastVal);
5118           ret->pushBackSilent(i);
5119         }
5120       else
5121         {
5122           types.insert(type);
5123           lastVal+=(icPtr[1]-icPtr[0]);
5124           newConnI->pushBackSilent(lastVal);
5125           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5126         }
5127     }
5128   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5129   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5130   return ret.retn();
5131 }
5132
5133 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)
5134 {
5135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5138   //
5139   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5140   DataArrayInt *conn1D=0,*conn1DI=0;
5141   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5142   DataArrayDouble *coordsTmp=0;
5143   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5144   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5146   const int *c1DPtr=conn1D->begin();
5147   const int *c1DIPtr=conn1DI->begin();
5148   int nbOfCells=getNumberOfCells();
5149   const int *cPtr=_nodal_connec->getConstPointer();
5150   const int *icPtr=_nodal_connec_index->getConstPointer();
5151   int lastVal=0;
5152   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5153     {
5154       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5155       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5156       if(!cm.isQuadratic())
5157         {
5158           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5159           types.insert(typ2); newConn->pushBackSilent(typ2);
5160           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5161           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5162             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5163           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5164           newConnI->pushBackSilent(lastVal);
5165           ret->pushBackSilent(i);
5166         }
5167       else
5168         {
5169           types.insert(typ);
5170           lastVal+=(icPtr[1]-icPtr[0]);
5171           newConnI->pushBackSilent(lastVal);
5172           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5173         }
5174     }
5175   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5176   return ret.retn();
5177 }
5178
5179 /*!
5180  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5181  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5182  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5183  */
5184 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5185 {
5186   
5187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5188   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5189   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5190 }
5191
5192 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5193 {
5194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5195   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5196   //
5197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5200   //
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5202   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5203   DataArrayInt *conn1D=0,*conn1DI=0;
5204   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5205   DataArrayDouble *coordsTmp=0;
5206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5207   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5209   const int *c1DPtr=conn1D->begin();
5210   const int *c1DIPtr=conn1DI->begin();
5211   int nbOfCells=getNumberOfCells();
5212   const int *cPtr=_nodal_connec->getConstPointer();
5213   const int *icPtr=_nodal_connec_index->getConstPointer();
5214   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5215   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5216     {
5217       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5218       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5219       if(!cm.isQuadratic())
5220         {
5221           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5222           types.insert(typ2); newConn->pushBackSilent(typ2);
5223           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5224           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5225             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5226           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5227           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5228           newConnI->pushBackSilent(lastVal);
5229           ret->pushBackSilent(i);
5230         }
5231       else
5232         {
5233           types.insert(typ);
5234           lastVal+=(icPtr[1]-icPtr[0]);
5235           newConnI->pushBackSilent(lastVal);
5236           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5237         }
5238     }
5239   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5240   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5241   return ret.retn();
5242 }
5243
5244 /*!
5245  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5246  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5247  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5248  */
5249 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5250 {
5251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5252   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5253   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5254 }
5255
5256 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5257 {
5258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5259   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5261   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5262   //
5263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5264   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5266   //
5267   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5268   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5269   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5270   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5271   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5274   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5278   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5279   int nbOfCells=getNumberOfCells();
5280   const int *cPtr=_nodal_connec->getConstPointer();
5281   const int *icPtr=_nodal_connec_index->getConstPointer();
5282   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5283   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5284     {
5285       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5286       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5287       if(!cm.isQuadratic())
5288         {
5289           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5290           if(typ2==INTERP_KERNEL::NORM_ERROR)
5291             {
5292               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5293               throw INTERP_KERNEL::Exception(oss.str().c_str());
5294             }
5295           types.insert(typ2); newConn->pushBackSilent(typ2);
5296           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5297           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5298             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5299           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5300             {
5301               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5302               int tmpPos=newConn->getNumberOfTuples();
5303               newConn->pushBackSilent(nodeId2);
5304               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5305             }
5306           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5307           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5308           newConnI->pushBackSilent(lastVal);
5309           ret->pushBackSilent(i);
5310         }
5311       else
5312         {
5313           types.insert(typ);
5314           lastVal+=(icPtr[1]-icPtr[0]);
5315           newConnI->pushBackSilent(lastVal);
5316           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5317         }
5318     }
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5321   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5322   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5323   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5324   int *c=newConn->getPointer();
5325   const int *cI(newConnI->begin());
5326   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5327     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5328   offset=coordsTmp2Safe->getNumberOfTuples();
5329   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5330     c[cI[(*elt)+1]-1]+=offset;
5331   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5332   return ret.retn();
5333 }
5334
5335 /*!
5336  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5337  * so that the number of cells remains the same. Quadratic faces are converted to
5338  * polygons. This method works only for 2D meshes in
5339  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5340  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5341  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5342  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5343  *         a polylinized edge constituting the input polygon.
5344  *  \throw If the coordinates array is not set.
5345  *  \throw If the nodal connectivity of cells is not defined.
5346  *  \throw If \a this->getMeshDimension() != 2.
5347  *  \throw If \a this->getSpaceDimension() != 2.
5348  */
5349 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5350 {
5351   checkFullyDefined();
5352   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5354   double epsa=fabs(eps);
5355   if(epsa<std::numeric_limits<double>::min())
5356     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 !");
5357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5361   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5362   revDesc1=0; revDescIndx1=0;
5363   mDesc->tessellate2DCurve(eps);
5364   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5365   setCoords(mDesc->getCoords());
5366 }
5367
5368 /*!
5369  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5370  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5371  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5372  *         a sub-divided edge.
5373  *  \throw If the coordinates array is not set.
5374  *  \throw If the nodal connectivity of cells is not defined.
5375  *  \throw If \a this->getMeshDimension() != 1.
5376  *  \throw If \a this->getSpaceDimension() != 2.
5377  */
5378 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5379 {
5380   checkFullyDefined();
5381   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5382     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5383   double epsa=fabs(eps);
5384   if(epsa<std::numeric_limits<double>::min())
5385     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 !");
5386   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5387   int nbCells=getNumberOfCells();
5388   int nbNodes=getNumberOfNodes();
5389   const int *conn=_nodal_connec->getConstPointer();
5390   const int *connI=_nodal_connec_index->getConstPointer();
5391   const double *coords=_coords->getConstPointer();
5392   std::vector<double> addCoo;
5393   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5395   newConnI->alloc(nbCells+1,1);
5396   int *newConnIPtr=newConnI->getPointer();
5397   *newConnIPtr=0;
5398   int tmp1[3];
5399   INTERP_KERNEL::Node *tmp2[3];
5400   std::set<INTERP_KERNEL::NormalizedCellType> types;
5401   for(int i=0;i<nbCells;i++,newConnIPtr++)
5402     {
5403       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5404       if(cm.isQuadratic())
5405         {//assert(connI[i+1]-connI[i]-1==3)
5406           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5407           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5408           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5409           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5410           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5411           if(eac)
5412             {
5413               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5414               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5415               delete eac;
5416               newConnIPtr[1]=(int)newConn.size();
5417             }
5418           else
5419             {
5420               types.insert(INTERP_KERNEL::NORM_SEG2);
5421               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5422               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5423               newConnIPtr[1]=newConnIPtr[0]+3;
5424             }
5425         }
5426       else
5427         {
5428           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5429           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5430           newConnIPtr[1]=newConnIPtr[0]+3;
5431         }
5432     }
5433   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5434     return ;
5435   _types=types;
5436   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5438   newConnArr->alloc((int)newConn.size(),1);
5439   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5440   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5441   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5442   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5443   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5444   std::copy(addCoo.begin(),addCoo.end(),work);
5445   DataArrayDouble::SetArrayIn(newCoords,_coords);
5446   updateTime();
5447 }
5448
5449 /*!
5450  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5451  * In addition, returns an array mapping new cells to old ones. <br>
5452  * This method typically increases the number of cells in \a this mesh
5453  * but the number of nodes remains \b unchanged.
5454  * That's why the 3D splitting policies
5455  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5456  *  \param [in] policy - specifies a pattern used for splitting.
5457  * The semantic of \a policy is:
5458  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5459  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5460  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5461  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5462  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5463  *          an id of old cell producing it. The caller is to delete this array using
5464  *         decrRef() as it is no more needed. 
5465  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5466  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5467  *          and \a this->getMeshDimension() != 3. 
5468  *  \throw If \a policy is not one of the four discussed above.
5469  *  \throw If the nodal connectivity of cells is not defined.
5470  */
5471 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5472 {
5473   switch(policy)
5474     {
5475     case 0:
5476       return simplexizePol0();
5477     case 1:
5478       return simplexizePol1();
5479     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5480       return simplexizePlanarFace5();
5481     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5482       return simplexizePlanarFace6();
5483     default:
5484       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)");
5485     }
5486 }
5487
5488 /*!
5489  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5490  * - 1D: INTERP_KERNEL::NORM_SEG2
5491  * - 2D: INTERP_KERNEL::NORM_TRI3
5492  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5493  *
5494  * This method is useful for users that need to use P1 field services as
5495  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5496  * All these methods need mesh support containing only simplex cells.
5497  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5498  *  \throw If the coordinates array is not set.
5499  *  \throw If the nodal connectivity of cells is not defined.
5500  *  \throw If \a this->getMeshDimension() < 1.
5501  */
5502 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5503 {
5504   checkFullyDefined();
5505   int mdim=getMeshDimension();
5506   if(mdim<1 || mdim>3)
5507     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5508   int nbCells=getNumberOfCells();
5509   const int *conn=_nodal_connec->getConstPointer();
5510   const int *connI=_nodal_connec_index->getConstPointer();
5511   for(int i=0;i<nbCells;i++)
5512     {
5513       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5514       if(!cm.isSimplex())
5515         return false;
5516     }
5517   return true;
5518 }
5519
5520 /*!
5521  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5522  */
5523 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5524 {
5525   checkConnectivityFullyDefined();
5526   if(getMeshDimension()!=2)
5527     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5528   int nbOfCells=getNumberOfCells();
5529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5530   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5531   ret->alloc(nbOfCells+nbOfCutCells,1);
5532   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5533   int *retPt=ret->getPointer();
5534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5536   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5537   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5538   int *pt=newConn->getPointer();
5539   int *ptI=newConnI->getPointer();
5540   ptI[0]=0;
5541   const int *oldc=_nodal_connec->getConstPointer();
5542   const int *ci=_nodal_connec_index->getConstPointer();
5543   for(int i=0;i<nbOfCells;i++,ci++)
5544     {
5545       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5546         {
5547           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5548                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5549           pt=std::copy(tmp,tmp+8,pt);
5550           ptI[1]=ptI[0]+4;
5551           ptI[2]=ptI[0]+8;
5552           *retPt++=i;
5553           *retPt++=i;
5554           ptI+=2;
5555         }
5556       else
5557         {
5558           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5559           ptI[1]=ptI[0]+ci[1]-ci[0];
5560           ptI++;
5561           *retPt++=i;
5562         }
5563     }
5564   _nodal_connec->decrRef();
5565   _nodal_connec=newConn.retn();
5566   _nodal_connec_index->decrRef();
5567   _nodal_connec_index=newConnI.retn();
5568   computeTypes();
5569   updateTime();
5570   return ret.retn();
5571 }
5572
5573 /*!
5574  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5575  */
5576 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5577 {
5578   checkConnectivityFullyDefined();
5579   if(getMeshDimension()!=2)
5580     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5581   int nbOfCells=getNumberOfCells();
5582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5583   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5584   ret->alloc(nbOfCells+nbOfCutCells,1);
5585   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5586   int *retPt=ret->getPointer();
5587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5589   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5590   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5591   int *pt=newConn->getPointer();
5592   int *ptI=newConnI->getPointer();
5593   ptI[0]=0;
5594   const int *oldc=_nodal_connec->getConstPointer();
5595   const int *ci=_nodal_connec_index->getConstPointer();
5596   for(int i=0;i<nbOfCells;i++,ci++)
5597     {
5598       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5599         {
5600           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5601                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5602           pt=std::copy(tmp,tmp+8,pt);
5603           ptI[1]=ptI[0]+4;
5604           ptI[2]=ptI[0]+8;
5605           *retPt++=i;
5606           *retPt++=i;
5607           ptI+=2;
5608         }
5609       else
5610         {
5611           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5612           ptI[1]=ptI[0]+ci[1]-ci[0];
5613           ptI++;
5614           *retPt++=i;
5615         }
5616     }
5617   _nodal_connec->decrRef();
5618   _nodal_connec=newConn.retn();
5619   _nodal_connec_index->decrRef();
5620   _nodal_connec_index=newConnI.retn();
5621   computeTypes();
5622   updateTime();
5623   return ret.retn();
5624 }
5625
5626 /*!
5627  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5628  */
5629 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5630 {
5631   checkConnectivityFullyDefined();
5632   if(getMeshDimension()!=3)
5633     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5634   int nbOfCells=getNumberOfCells();
5635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5636   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5637   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5638   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5639   int *retPt=ret->getPointer();
5640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5642   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5643   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5644   int *pt=newConn->getPointer();
5645   int *ptI=newConnI->getPointer();
5646   ptI[0]=0;
5647   const int *oldc=_nodal_connec->getConstPointer();
5648   const int *ci=_nodal_connec_index->getConstPointer();
5649   for(int i=0;i<nbOfCells;i++,ci++)
5650     {
5651       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5652         {
5653           for(int j=0;j<5;j++,pt+=5,ptI++)
5654             {
5655               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5656               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];
5657               *retPt++=i;
5658               ptI[1]=ptI[0]+5;
5659             }
5660         }
5661       else
5662         {
5663           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5664           ptI[1]=ptI[0]+ci[1]-ci[0];
5665           ptI++;
5666           *retPt++=i;
5667         }
5668     }
5669   _nodal_connec->decrRef();
5670   _nodal_connec=newConn.retn();
5671   _nodal_connec_index->decrRef();
5672   _nodal_connec_index=newConnI.retn();
5673   computeTypes();
5674   updateTime();
5675   return ret.retn();
5676 }
5677
5678 /*!
5679  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5680  */
5681 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5682 {
5683   checkConnectivityFullyDefined();
5684   if(getMeshDimension()!=3)
5685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5686   int nbOfCells=getNumberOfCells();
5687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5688   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5689   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5690   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5691   int *retPt=ret->getPointer();
5692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5694   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5695   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5696   int *pt=newConn->getPointer();
5697   int *ptI=newConnI->getPointer();
5698   ptI[0]=0;
5699   const int *oldc=_nodal_connec->getConstPointer();
5700   const int *ci=_nodal_connec_index->getConstPointer();
5701   for(int i=0;i<nbOfCells;i++,ci++)
5702     {
5703       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5704         {
5705           for(int j=0;j<6;j++,pt+=5,ptI++)
5706             {
5707               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5708               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];
5709               *retPt++=i;
5710               ptI[1]=ptI[0]+5;
5711             }
5712         }
5713       else
5714         {
5715           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5716           ptI[1]=ptI[0]+ci[1]-ci[0];
5717           ptI++;
5718           *retPt++=i;
5719         }
5720     }
5721   _nodal_connec->decrRef();
5722   _nodal_connec=newConn.retn();
5723   _nodal_connec_index->decrRef();
5724   _nodal_connec_index=newConnI.retn();
5725   computeTypes();
5726   updateTime();
5727   return ret.retn();
5728 }
5729
5730 /*!
5731  * 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.
5732  * This method completly ignore coordinates.
5733  * @param nodeSubdived is the nodal connectivity of subdivision of edges
5734  * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5735  * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5736  * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5737  */
5738 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5739 {
5740   checkFullyDefined();
5741   if(getMeshDimension()!=2)
5742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5743   int nbOfCells=getNumberOfCells();
5744   int *connI=_nodal_connec_index->getPointer();
5745   int newConnLgth=0;
5746   for(int i=0;i<nbOfCells;i++,connI++)
5747     {
5748       int offset=descIndex[i];
5749       int nbOfEdges=descIndex[i+1]-offset;
5750       //
5751       bool ddirect=desc[offset+nbOfEdges-1]>0;
5752       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5753       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5754       for(int j=0;j<nbOfEdges;j++)
5755         {
5756           bool direct=desc[offset+j]>0;
5757           int edgeId=std::abs(desc[offset+j])-1;
5758           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5759             {
5760               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5761               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5762               int ref2=direct?id1:id2;
5763               if(ref==ref2)
5764                 {
5765                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5766                   newConnLgth+=nbOfSubNodes-1;
5767                   ref=direct?id2:id1;
5768                 }
5769               else
5770                 {
5771                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5772                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5773                 }
5774             }
5775           else
5776             {
5777               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5778             }
5779         }
5780       newConnLgth++;//+1 is for cell type
5781       connI[1]=newConnLgth;
5782     }
5783   //
5784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5785   newConn->alloc(newConnLgth,1);
5786   int *work=newConn->getPointer();
5787   for(int i=0;i<nbOfCells;i++)
5788     {
5789       *work++=INTERP_KERNEL::NORM_POLYGON;
5790       int offset=descIndex[i];
5791       int nbOfEdges=descIndex[i+1]-offset;
5792       for(int j=0;j<nbOfEdges;j++)
5793         {
5794           bool direct=desc[offset+j]>0;
5795           int edgeId=std::abs(desc[offset+j])-1;
5796           if(direct)
5797             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5798           else
5799             {
5800               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5801               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5802               work=std::copy(it,it+nbOfSubNodes-1,work);
5803             }
5804         }
5805     }
5806   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5807   _types.clear();
5808   if(nbOfCells>0)
5809     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5810 }
5811
5812 /*!
5813  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5814  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5815  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5816  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5817  * so it can be useful to call mergeNodes() before calling this method.
5818  *  \throw If \a this->getMeshDimension() <= 1.
5819  *  \throw If the coordinates array is not set.
5820  *  \throw If the nodal connectivity of cells is not defined.
5821  */
5822 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5823 {
5824   checkFullyDefined();
5825   if(getMeshDimension()<=1)
5826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5827   int nbOfCells=getNumberOfCells();
5828   if(nbOfCells<1)
5829     return ;
5830   int initMeshLgth=getMeshLength();
5831   int *conn=_nodal_connec->getPointer();
5832   int *index=_nodal_connec_index->getPointer();
5833   int posOfCurCell=0;
5834   int newPos=0;
5835   int lgthOfCurCell;
5836   for(int i=0;i<nbOfCells;i++)
5837     {
5838       lgthOfCurCell=index[i+1]-posOfCurCell;
5839       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5840       int newLgth;
5841       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5842                                                                                                      conn+newPos+1,newLgth);
5843       conn[newPos]=newType;
5844       newPos+=newLgth+1;
5845       posOfCurCell=index[i+1];
5846       index[i+1]=newPos;
5847     }
5848   if(newPos!=initMeshLgth)
5849     _nodal_connec->reAlloc(newPos);
5850   computeTypes();
5851 }
5852
5853 /*!
5854  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5855  * A cell is considered to be oriented correctly if an angle between its
5856  * normal vector and a given vector is less than \c PI / \c 2.
5857  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5858  *         cells. 
5859  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5860  *         checked.
5861  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5862  *         is not cleared before filling in.
5863  *  \throw If \a this->getMeshDimension() != 2.
5864  *  \throw If \a this->getSpaceDimension() != 3.
5865  *
5866  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5867  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5868  */
5869 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5870 {
5871   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5872     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5873   int nbOfCells=getNumberOfCells();
5874   const int *conn=_nodal_connec->getConstPointer();
5875   const int *connI=_nodal_connec_index->getConstPointer();
5876   const double *coordsPtr=_coords->getConstPointer();
5877   for(int i=0;i<nbOfCells;i++)
5878     {
5879       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5880       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5881         {
5882           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5883           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5884             cells.push_back(i);
5885         }
5886     }
5887 }
5888
5889 /*!
5890  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5891  * considered to be oriented correctly if an angle between its normal vector and a
5892  * given vector is less than \c PI / \c 2. 
5893  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5894  *         cells. 
5895  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5896  *         checked.
5897  *  \throw If \a this->getMeshDimension() != 2.
5898  *  \throw If \a this->getSpaceDimension() != 3.
5899  *
5900  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5901  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5902  */
5903 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5904 {
5905   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5906     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5907   int nbOfCells=getNumberOfCells();
5908   int *conn=_nodal_connec->getPointer();
5909   const int *connI=_nodal_connec_index->getConstPointer();
5910   const double *coordsPtr=_coords->getConstPointer();
5911   bool isModified=false;
5912   for(int i=0;i<nbOfCells;i++)
5913     {
5914       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5915       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5916         {
5917           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5918           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5919             {
5920               isModified=true;
5921               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5922               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5923               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5924             }
5925         }
5926     }
5927   if(isModified)
5928     _nodal_connec->declareAsNew();
5929   updateTime();
5930 }
5931
5932 /*!
5933  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5934  * oriented facets. The normal vector of the facet should point out of the cell.
5935  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5936  *         is not cleared before filling in.
5937  *  \throw If \a this->getMeshDimension() != 3.
5938  *  \throw If \a this->getSpaceDimension() != 3.
5939  *  \throw If the coordinates array is not set.
5940  *  \throw If the nodal connectivity of cells is not defined.
5941  *
5942  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5943  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5944  */
5945 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5946 {
5947   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5948     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5949   int nbOfCells=getNumberOfCells();
5950   const int *conn=_nodal_connec->getConstPointer();
5951   const int *connI=_nodal_connec_index->getConstPointer();
5952   const double *coordsPtr=_coords->getConstPointer();
5953   for(int i=0;i<nbOfCells;i++)
5954     {
5955       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5956       if(type==INTERP_KERNEL::NORM_POLYHED)
5957         {
5958           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5959             cells.push_back(i);
5960         }
5961     }
5962 }
5963
5964 /*!
5965  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5966  * out of the cell. 
5967  *  \throw If \a this->getMeshDimension() != 3.
5968  *  \throw If \a this->getSpaceDimension() != 3.
5969  *  \throw If the coordinates array is not set.
5970  *  \throw If the nodal connectivity of cells is not defined.
5971  *  \throw If the reparation fails.
5972  *
5973  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5974  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5975  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5976  */
5977 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5978 {
5979   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5980     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5981   int nbOfCells=getNumberOfCells();
5982   int *conn=_nodal_connec->getPointer();
5983   const int *connI=_nodal_connec_index->getConstPointer();
5984   const double *coordsPtr=_coords->getConstPointer();
5985   for(int i=0;i<nbOfCells;i++)
5986     {
5987       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5988       if(type==INTERP_KERNEL::NORM_POLYHED)
5989         {
5990           try
5991             {
5992               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5993                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5994             }
5995           catch(INTERP_KERNEL::Exception& e)
5996             {
5997               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5998               throw INTERP_KERNEL::Exception(oss.str().c_str());
5999             }
6000         }
6001     }
6002   updateTime();
6003 }
6004
6005 /*!
6006  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6007  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6008  * according to which the first facet of the cell should be oriented to have the normal vector
6009  * pointing out of cell.
6010  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6011  *         cells. The caller is to delete this array using decrRef() as it is no more
6012  *         needed. 
6013  *  \throw If \a this->getMeshDimension() != 3.
6014  *  \throw If \a this->getSpaceDimension() != 3.
6015  *  \throw If the coordinates array is not set.
6016  *  \throw If the nodal connectivity of cells is not defined.
6017  *
6018  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6019  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6020  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6021  */
6022 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
6023 {
6024   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6025   if(getMeshDimension()!=3)
6026     throw INTERP_KERNEL::Exception(msg);
6027   int spaceDim=getSpaceDimension();
6028   if(spaceDim!=3)
6029     throw INTERP_KERNEL::Exception(msg);
6030   //
6031   int nbOfCells=getNumberOfCells();
6032   int *conn=_nodal_connec->getPointer();
6033   const int *connI=_nodal_connec_index->getConstPointer();
6034   const double *coo=getCoords()->getConstPointer();
6035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6036   for(int i=0;i<nbOfCells;i++)
6037     {
6038       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6039       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6040         {
6041           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6042             {
6043               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6044               cells->pushBackSilent(i);
6045             }
6046         }
6047     }
6048   return cells.retn();
6049 }
6050
6051 /*!
6052  * This method is a faster method to correct orientation of all 3D cells in \a this.
6053  * 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.
6054  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6055  * 
6056  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6057  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6058  */
6059 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
6060 {
6061   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6062     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6063   int nbOfCells=getNumberOfCells();
6064   int *conn=_nodal_connec->getPointer();
6065   const int *connI=_nodal_connec_index->getConstPointer();
6066   const double *coordsPtr=_coords->getConstPointer();
6067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6068   for(int i=0;i<nbOfCells;i++)
6069     {
6070       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6071       switch(type)
6072         {
6073         case INTERP_KERNEL::NORM_TETRA4:
6074           {
6075             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6076               {
6077                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6078                 ret->pushBackSilent(i);
6079               }
6080             break;
6081           }
6082         case INTERP_KERNEL::NORM_PYRA5:
6083           {
6084             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6085               {
6086                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6087                 ret->pushBackSilent(i);
6088               }
6089             break;
6090           }
6091         case INTERP_KERNEL::NORM_PENTA6:
6092         case INTERP_KERNEL::NORM_HEXA8:
6093         case INTERP_KERNEL::NORM_HEXGP12:
6094           {
6095             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6096               {
6097                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6098                 ret->pushBackSilent(i);
6099               }
6100             break;
6101           }
6102         case INTERP_KERNEL::NORM_POLYHED:
6103           {
6104             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6105               {
6106                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6107                 ret->pushBackSilent(i);
6108               }
6109             break;
6110           }
6111         default:
6112           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 !");
6113         }
6114     }
6115   updateTime();
6116   return ret.retn();
6117 }
6118
6119 /*!
6120  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6121  * If it is not the case an exception will be thrown.
6122  * This method is fast because the first cell of 'this' is used to compute the plane.
6123  * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6124  * @param pos output of size at least 3 used to store a point owned of searched plane.
6125  */
6126 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
6127 {
6128   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6129     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6130   const int *conn=_nodal_connec->getConstPointer();
6131   const int *connI=_nodal_connec_index->getConstPointer();
6132   const double *coordsPtr=_coords->getConstPointer();
6133   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6134   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6135 }
6136
6137 /*!
6138  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6139  * cells. Currently cells of the following types are treated:
6140  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6141  * For a cell of other type an exception is thrown.
6142  * Space dimension of a 2D mesh can be either 2 or 3.
6143  * The Edge Ratio of a cell \f$t\f$ is: 
6144  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6145  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6146  *  the smallest edge lengths of \f$t\f$.
6147  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6148  *          cells and one time, lying on \a this mesh. The caller is to delete this
6149  *          field using decrRef() as it is no more needed. 
6150  *  \throw If the coordinates array is not set.
6151  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6152  *  \throw If the connectivity data array has more than one component.
6153  *  \throw If the connectivity data array has a named component.
6154  *  \throw If the connectivity index data array has more than one component.
6155  *  \throw If the connectivity index data array has a named component.
6156  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6157  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6158  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6159  */
6160 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
6161 {
6162   checkCoherency();
6163   int spaceDim=getSpaceDimension();
6164   int meshDim=getMeshDimension();
6165   if(spaceDim!=2 && spaceDim!=3)
6166     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6167   if(meshDim!=2 && meshDim!=3)
6168     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6169   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6170   ret->setMesh(this);
6171   int nbOfCells=getNumberOfCells();
6172   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6173   arr->alloc(nbOfCells,1);
6174   double *pt=arr->getPointer();
6175   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6176   const int *conn=_nodal_connec->getConstPointer();
6177   const int *connI=_nodal_connec_index->getConstPointer();
6178   const double *coo=_coords->getConstPointer();
6179   double tmp[12];
6180   for(int i=0;i<nbOfCells;i++,pt++)
6181     {
6182       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6183       switch(t)
6184         {
6185           case INTERP_KERNEL::NORM_TRI3:
6186             {
6187               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6188               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6189               break;
6190             }
6191           case INTERP_KERNEL::NORM_QUAD4:
6192             {
6193               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6194               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6195               break;
6196             }
6197           case INTERP_KERNEL::NORM_TETRA4:
6198             {
6199               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6200               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6201               break;
6202             }
6203         default:
6204           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6205         }
6206       conn+=connI[i+1]-connI[i];
6207     }
6208   ret->setName("EdgeRatio");
6209   ret->synchronizeTimeWithSupport();
6210   return ret.retn();
6211 }
6212
6213 /*!
6214  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6215  * cells. Currently cells of the following types are treated:
6216  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6217  * For a cell of other type an exception is thrown.
6218  * Space dimension of a 2D mesh can be either 2 or 3.
6219  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6220  *          cells and one time, lying on \a this mesh. The caller is to delete this
6221  *          field using decrRef() as it is no more needed. 
6222  *  \throw If the coordinates array is not set.
6223  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6224  *  \throw If the connectivity data array has more than one component.
6225  *  \throw If the connectivity data array has a named component.
6226  *  \throw If the connectivity index data array has more than one component.
6227  *  \throw If the connectivity index data array has a named component.
6228  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6229  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6230  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6231  */
6232 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6233 {
6234   checkCoherency();
6235   int spaceDim=getSpaceDimension();
6236   int meshDim=getMeshDimension();
6237   if(spaceDim!=2 && spaceDim!=3)
6238     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6239   if(meshDim!=2 && meshDim!=3)
6240     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6241   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6242   ret->setMesh(this);
6243   int nbOfCells=getNumberOfCells();
6244   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6245   arr->alloc(nbOfCells,1);
6246   double *pt=arr->getPointer();
6247   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6248   const int *conn=_nodal_connec->getConstPointer();
6249   const int *connI=_nodal_connec_index->getConstPointer();
6250   const double *coo=_coords->getConstPointer();
6251   double tmp[12];
6252   for(int i=0;i<nbOfCells;i++,pt++)
6253     {
6254       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6255       switch(t)
6256         {
6257           case INTERP_KERNEL::NORM_TRI3:
6258             {
6259               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6260               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6261               break;
6262             }
6263           case INTERP_KERNEL::NORM_QUAD4:
6264             {
6265               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6266               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6267               break;
6268             }
6269           case INTERP_KERNEL::NORM_TETRA4:
6270             {
6271               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6272               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6273               break;
6274             }
6275         default:
6276           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6277         }
6278       conn+=connI[i+1]-connI[i];
6279     }
6280   ret->setName("AspectRatio");
6281   ret->synchronizeTimeWithSupport();
6282   return ret.retn();
6283 }
6284
6285 /*!
6286  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6287  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6288  * treated: INTERP_KERNEL::NORM_QUAD4.
6289  * For a cell of other type an exception is thrown.
6290  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6291  *          cells and one time, lying on \a this mesh. The caller is to delete this
6292  *          field using decrRef() as it is no more needed. 
6293  *  \throw If the coordinates array is not set.
6294  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6295  *  \throw If the connectivity data array has more than one component.
6296  *  \throw If the connectivity data array has a named component.
6297  *  \throw If the connectivity index data array has more than one component.
6298  *  \throw If the connectivity index data array has a named component.
6299  *  \throw If \a this->getMeshDimension() != 2.
6300  *  \throw If \a this->getSpaceDimension() != 3.
6301  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6302  */
6303 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6304 {
6305   checkCoherency();
6306   int spaceDim=getSpaceDimension();
6307   int meshDim=getMeshDimension();
6308   if(spaceDim!=3)
6309     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6310   if(meshDim!=2)
6311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6312   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6313   ret->setMesh(this);
6314   int nbOfCells=getNumberOfCells();
6315   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6316   arr->alloc(nbOfCells,1);
6317   double *pt=arr->getPointer();
6318   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6319   const int *conn=_nodal_connec->getConstPointer();
6320   const int *connI=_nodal_connec_index->getConstPointer();
6321   const double *coo=_coords->getConstPointer();
6322   double tmp[12];
6323   for(int i=0;i<nbOfCells;i++,pt++)
6324     {
6325       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6326       switch(t)
6327         {
6328           case INTERP_KERNEL::NORM_QUAD4:
6329             {
6330               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6331               *pt=INTERP_KERNEL::quadWarp(tmp);
6332               break;
6333             }
6334         default:
6335           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6336         }
6337       conn+=connI[i+1]-connI[i];
6338     }
6339   ret->setName("Warp");
6340   ret->synchronizeTimeWithSupport();
6341   return ret.retn();
6342 }
6343
6344
6345 /*!
6346  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6347  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6348  * treated: INTERP_KERNEL::NORM_QUAD4.
6349  * For a cell of other type an exception is thrown.
6350  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6351  *          cells and one time, lying on \a this mesh. The caller is to delete this
6352  *          field using decrRef() as it is no more needed. 
6353  *  \throw If the coordinates array is not set.
6354  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6355  *  \throw If the connectivity data array has more than one component.
6356  *  \throw If the connectivity data array has a named component.
6357  *  \throw If the connectivity index data array has more than one component.
6358  *  \throw If the connectivity index data array has a named component.
6359  *  \throw If \a this->getMeshDimension() != 2.
6360  *  \throw If \a this->getSpaceDimension() != 3.
6361  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6362  */
6363 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6364 {
6365   checkCoherency();
6366   int spaceDim=getSpaceDimension();
6367   int meshDim=getMeshDimension();
6368   if(spaceDim!=3)
6369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6370   if(meshDim!=2)
6371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6372   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6373   ret->setMesh(this);
6374   int nbOfCells=getNumberOfCells();
6375   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6376   arr->alloc(nbOfCells,1);
6377   double *pt=arr->getPointer();
6378   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6379   const int *conn=_nodal_connec->getConstPointer();
6380   const int *connI=_nodal_connec_index->getConstPointer();
6381   const double *coo=_coords->getConstPointer();
6382   double tmp[12];
6383   for(int i=0;i<nbOfCells;i++,pt++)
6384     {
6385       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6386       switch(t)
6387         {
6388           case INTERP_KERNEL::NORM_QUAD4:
6389             {
6390               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6391               *pt=INTERP_KERNEL::quadSkew(tmp);
6392               break;
6393             }
6394         default:
6395           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6396         }
6397       conn+=connI[i+1]-connI[i];
6398     }
6399   ret->setName("Skew");
6400   ret->synchronizeTimeWithSupport();
6401   return ret.retn();
6402 }
6403
6404 /*!
6405  * This method aggregate the bbox of each cell and put it into bbox parameter.
6406  * @param bbox out parameter of size 2*spacedim*nbOfcells.
6407  */
6408 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6409 {
6410   int spaceDim=getSpaceDimension();
6411   int nbOfCells=getNumberOfCells();
6412   bbox.resize(2*nbOfCells*spaceDim);
6413   for(int i=0;i<nbOfCells*spaceDim;i++)
6414     {
6415       bbox[2*i]=std::numeric_limits<double>::max();
6416       bbox[2*i+1]=-std::numeric_limits<double>::max();
6417     }
6418   const double *coordsPtr=_coords->getConstPointer();
6419   const int *conn=_nodal_connec->getConstPointer();
6420   const int *connI=_nodal_connec_index->getConstPointer();
6421   for(int i=0;i<nbOfCells;i++)
6422     {
6423       int offset=connI[i]+1;
6424       int nbOfNodesForCell=connI[i+1]-offset;
6425       for(int j=0;j<nbOfNodesForCell;j++)
6426         {
6427           int nodeId=conn[offset+j];
6428           if(nodeId>=0)
6429             for(int k=0;k<spaceDim;k++)
6430               {
6431                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6432                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6433               }
6434         }
6435     }
6436 }
6437
6438 /// @cond INTERNAL
6439
6440 namespace ParaMEDMEMImpl
6441 {
6442   class ConnReader
6443   {
6444   public:
6445     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6446     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6447   private:
6448     const int *_conn;
6449     int _val;
6450   };
6451
6452   class ConnReader2
6453   {
6454   public:
6455     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6456     bool operator() (const int& pos) { return _conn[pos]==_val; }
6457   private:
6458     const int *_conn;
6459     int _val;
6460   };
6461 }
6462
6463 /// @endcond
6464
6465 /*!
6466  * This method expects that 'this' is sorted by types. If not an exception will be thrown.
6467  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6468  * 'this' is composed in cell types.
6469  * The returned array is of size 3*n where n is the number of different types present in 'this'. 
6470  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6471  * This parameter is kept only for compatibility with other methode listed above.
6472  */
6473 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6474 {
6475   checkConnectivityFullyDefined();
6476   const int *conn=_nodal_connec->getConstPointer();
6477   const int *connI=_nodal_connec_index->getConstPointer();
6478   const int *work=connI;
6479   int nbOfCells=getNumberOfCells();
6480   std::size_t n=getAllTypes().size();
6481   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6482   std::set<INTERP_KERNEL::NormalizedCellType> types;
6483   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6484     {
6485       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6486       if(types.find(typ)!=types.end())
6487         {
6488           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6489           oss << " is not contiguous !";
6490           throw INTERP_KERNEL::Exception(oss.str().c_str());
6491         }
6492       types.insert(typ);
6493       ret[3*i]=typ;
6494       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6495       ret[3*i+1]=(int)std::distance(work,work2);
6496       work=work2;
6497     }
6498   return ret;
6499 }
6500
6501 /*!
6502  * This method is used to check that this has contiguous cell type in same order than described in 'code'.
6503  * only for types cell, type node is not managed.
6504  * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
6505  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6506  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6507  * If 2 or more same geometric type is in 'code' and exception is thrown too.
6508  *
6509  * This method firstly checks
6510  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6511  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6512  * an exception is thrown too.
6513  * 
6514  * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
6515  * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown 
6516  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6517  */
6518 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6519 {
6520   if(code.empty())
6521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6522   std::size_t sz=code.size();
6523   std::size_t n=sz/3;
6524   if(sz%3!=0)
6525     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6526   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6527   int nb=0;
6528   for(std::size_t i=0;i<n;i++)
6529     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6530       {
6531         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6532         nb+=code[3*i+1];
6533         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6534           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6535       }
6536   if(types.size()!=n)
6537     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6538   if(idsPerType.empty())
6539     {
6540       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6541         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6542       if(types.size()==_types.size())
6543         return 0;
6544     }
6545   DataArrayInt *ret=DataArrayInt::New();
6546   ret->alloc(nb,1);
6547   int *retPtr=ret->getPointer();
6548   const int *connI=_nodal_connec_index->getConstPointer();
6549   const int *conn=_nodal_connec->getConstPointer();
6550   int nbOfCells=getNumberOfCells();
6551   const int *i=connI;
6552   int kk=0;
6553   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6554     {
6555       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6556       int offset=(int)std::distance(connI,i);
6557       if(code[3*kk+2]==-1)
6558         {
6559           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6560           std::size_t pos2=std::distance(i,j);
6561           for(std::size_t k=0;k<pos2;k++)
6562             *retPtr++=(int)k+offset;
6563           i=j;
6564         }
6565       else
6566         {
6567           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6568                                 retPtr,std::bind2nd(std::plus<int>(),offset));
6569         }
6570     }
6571   return ret;
6572 }
6573
6574 /*!
6575  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6576  * 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.
6577  * 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.
6578  * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
6579  * 
6580  * @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.
6581  * @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,
6582  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6583  * @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.
6584  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6585  * @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
6586  */
6587 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6588 {
6589   if(profile->getNumberOfComponents()!=1)
6590     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6591   checkConnectivityFullyDefined();
6592   const int *conn=_nodal_connec->getConstPointer();
6593   const int *connI=_nodal_connec_index->getConstPointer();
6594   int nbOfCells=getNumberOfCells();
6595   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6596   std::vector<int> typeRangeVals(1);
6597   for(const int *i=connI;i!=connI+nbOfCells;)
6598     {
6599       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6600       if(std::find(types.begin(),types.end(),curType)!=types.end())
6601         {
6602           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6603         }
6604       types.push_back(curType);
6605       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6606       typeRangeVals.push_back((int)std::distance(connI,i));
6607     }
6608   //
6609   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6610   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6611   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6613   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6614   //
6615   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6616   code.resize(3*nbOfCastsFinal);
6617   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6618   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6619   for(int i=0;i<nbOfCastsFinal;i++)
6620     {
6621       int castId=castsPresent->getIJ(i,0);
6622       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6623       idsInPflPerType2.push_back(tmp3);
6624       code[3*i]=(int)types[castId];
6625       code[3*i+1]=tmp3->getNumberOfTuples();
6626       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6627       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6628         {
6629           tmp4->copyStringInfoFrom(*profile);
6630           idsPerType2.push_back(tmp4);
6631           code[3*i+2]=(int)idsPerType2.size()-1;
6632         }
6633       else
6634         {
6635           code[3*i+2]=-1;
6636         }
6637     }
6638   std::size_t sz2=idsInPflPerType2.size();
6639   idsInPflPerType.resize(sz2);
6640   for(std::size_t i=0;i<sz2;i++)
6641     {
6642       DataArrayInt *locDa=idsInPflPerType2[i];
6643       locDa->incrRef();
6644       idsInPflPerType[i]=locDa;
6645     }
6646   std::size_t sz=idsPerType2.size();
6647   idsPerType.resize(sz);
6648   for(std::size_t i=0;i<sz;i++)
6649     {
6650       DataArrayInt *locDa=idsPerType2[i];
6651       locDa->incrRef();
6652       idsPerType[i]=locDa;
6653     }
6654 }
6655
6656 /*!
6657  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6658  * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6659  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6660  * 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.
6661  */
6662 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6663 {
6664   checkFullyDefined();
6665   nM1LevMesh->checkFullyDefined();
6666   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6667     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6668   if(_coords!=nM1LevMesh->getCoords())
6669     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6671   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6672   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6674   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6675   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6676   tmp->setConnectivity(tmp0,tmp1);
6677   tmp->renumberCells(ret0->getConstPointer(),false);
6678   revDesc=tmp->getNodalConnectivity();
6679   revDescIndx=tmp->getNodalConnectivityIndex();
6680   DataArrayInt *ret=0;
6681   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6682     {
6683       int tmp2;
6684       ret->getMaxValue(tmp2);
6685       ret->decrRef();
6686       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6687       throw INTERP_KERNEL::Exception(oss.str().c_str());
6688     }
6689   nM1LevMeshIds=ret;
6690   //
6691   revDesc->incrRef();
6692   revDescIndx->incrRef();
6693   ret1->incrRef();
6694   ret0->incrRef();
6695   meshnM1Old2New=ret0;
6696   return ret1;
6697 }
6698
6699 /*!
6700  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6701  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6702  * in "Old to New" mode.
6703  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6704  *          this array using decrRef() as it is no more needed.
6705  *  \throw If the nodal connectivity of cells is not defined.
6706  */
6707 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6708 {
6709   checkConnectivityFullyDefined();
6710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6711   renumberCells(ret->getConstPointer(),false);
6712   return ret.retn();
6713 }
6714
6715 /*!
6716  * This methods checks that cells are sorted by their types.
6717  * This method makes asumption (no check) that connectivity is correctly set before calling.
6718  */
6719 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6720 {
6721   checkFullyDefined();
6722   const int *conn=_nodal_connec->getConstPointer();
6723   const int *connI=_nodal_connec_index->getConstPointer();
6724   int nbOfCells=getNumberOfCells();
6725   std::set<INTERP_KERNEL::NormalizedCellType> types;
6726   for(const int *i=connI;i!=connI+nbOfCells;)
6727     {
6728       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6729       if(types.find(curType)!=types.end())
6730         return false;
6731       types.insert(curType);
6732       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6733     }
6734   return true;
6735 }
6736
6737 /*!
6738  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6739  * The geometric type order is specified by MED file.
6740  * 
6741  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6742  */
6743 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6744 {
6745   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6746 }
6747
6748 /*!
6749  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6750  * that the order is specified in array defined by [orderBg,orderEnd).
6751  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6752  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6753  */
6754 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6755 {
6756   checkFullyDefined();
6757   const int *conn=_nodal_connec->getConstPointer();
6758   const int *connI=_nodal_connec_index->getConstPointer();
6759   int nbOfCells=getNumberOfCells();
6760   if(nbOfCells==0)
6761     return true;
6762   int lastPos=-1;
6763   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6764   for(const int *i=connI;i!=connI+nbOfCells;)
6765     {
6766       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6767       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6768       if(isTypeExists!=orderEnd)
6769         {
6770           int pos=(int)std::distance(orderBg,isTypeExists);
6771           if(pos<=lastPos)
6772             return false;
6773           lastPos=pos;
6774           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6775         }
6776       else
6777         {
6778           if(sg.find(curType)==sg.end())
6779             {
6780               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6781               sg.insert(curType);
6782             }
6783           else
6784             return false;
6785         }
6786     }
6787   return true;
6788 }
6789
6790 /*!
6791  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6792  * 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
6793  * 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'.
6794  */
6795 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6796 {
6797   checkConnectivityFullyDefined();
6798   int nbOfCells=getNumberOfCells();
6799   const int *conn=_nodal_connec->getConstPointer();
6800   const int *connI=_nodal_connec_index->getConstPointer();
6801   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6803   tmpa->alloc(nbOfCells,1);
6804   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6805   tmpb->fillWithZero();
6806   int *tmp=tmpa->getPointer();
6807   int *tmp2=tmpb->getPointer();
6808   for(const int *i=connI;i!=connI+nbOfCells;i++)
6809     {
6810       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6811       if(where!=orderEnd)
6812         {
6813           int pos=(int)std::distance(orderBg,where);
6814           tmp2[pos]++;
6815           tmp[std::distance(connI,i)]=pos;
6816         }
6817       else
6818         {
6819           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6820           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6821           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6822           throw INTERP_KERNEL::Exception(oss.str().c_str());
6823         }
6824     }
6825   nbPerType=tmpb.retn();
6826   return tmpa.retn();
6827 }
6828
6829 /*!
6830  * 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'.
6831  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6832  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6833  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6834  */
6835 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6836 {
6837   DataArrayInt *nbPerType=0;
6838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6839   nbPerType->decrRef();
6840   return tmpa->buildPermArrPerLevel();
6841 }
6842
6843 /*!
6844  * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6845  * The number of cells remains unchanged after the call of this method.
6846  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6847  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6848  *
6849  * @return the array giving the correspondance old to new.
6850  */
6851 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6852 {
6853   checkFullyDefined();
6854   computeTypes();
6855   const int *conn=_nodal_connec->getConstPointer();
6856   const int *connI=_nodal_connec_index->getConstPointer();
6857   int nbOfCells=getNumberOfCells();
6858   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6859   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6860     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6861       {
6862         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6863         types.push_back(curType);
6864         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6865       }
6866   DataArrayInt *ret=DataArrayInt::New();
6867   ret->alloc(nbOfCells,1);
6868   int *retPtr=ret->getPointer();
6869   std::fill(retPtr,retPtr+nbOfCells,-1);
6870   int newCellId=0;
6871   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6872     {
6873       for(const int *i=connI;i!=connI+nbOfCells;i++)
6874         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6875           retPtr[std::distance(connI,i)]=newCellId++;
6876     }
6877   renumberCells(retPtr,false);
6878   return ret;
6879 }
6880
6881 /*!
6882  * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6883  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6884  * This method makes asumption that connectivity is correctly set before calling.
6885  */
6886 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6887 {
6888   checkFullyDefined();
6889   const int *conn=_nodal_connec->getConstPointer();
6890   const int *connI=_nodal_connec_index->getConstPointer();
6891   int nbOfCells=getNumberOfCells();
6892   std::vector<MEDCouplingUMesh *> ret;
6893   for(const int *i=connI;i!=connI+nbOfCells;)
6894     {
6895       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6896       int beginCellId=(int)std::distance(connI,i);
6897       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6898       int endCellId=(int)std::distance(connI,i);
6899       int sz=endCellId-beginCellId;
6900       int *cells=new int[sz];
6901       for(int j=0;j<sz;j++)
6902         cells[j]=beginCellId+j;
6903       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6904       delete [] cells;
6905       ret.push_back(m);
6906     }
6907   return ret;
6908 }
6909
6910 /*!
6911  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6912  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6913  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6914  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6915  * are not used here to avoid the build of big permutation array.
6916  *
6917  * \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
6918  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6919  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6920  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6921  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6922  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6923  * \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
6924  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6925  */
6926 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6927                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6928                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6929 {
6930   std::vector<const MEDCouplingUMesh *> ms2;
6931   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6932     if(*it)
6933       {
6934         (*it)->checkConnectivityFullyDefined();
6935         ms2.push_back(*it);
6936       }
6937   if(ms2.empty())
6938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6939   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6940   int meshDim=ms2[0]->getMeshDimension();
6941   std::vector<const MEDCouplingUMesh *> m1ssm;
6942   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6943   //
6944   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6945   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6946   int fake=0,rk=0;
6947   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6948   ret1->alloc(0,1); ret2->alloc(0,1);
6949   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6950     {
6951       if(meshDim!=(*it)->getMeshDimension())
6952         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6953       if(refCoo!=(*it)->getCoords())
6954         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6955       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6956       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6957       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6958       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6959         {
6960           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6961           m1ssmSingleAuto.push_back(singleCell);
6962           m1ssmSingle.push_back(singleCell);
6963           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6964         }
6965     }
6966   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6967   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6968   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6969   for(std::size_t i=0;i<m1ssm.size();i++)
6970     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6971   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6972   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6973   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6974   return ret0.retn();
6975 }
6976
6977 /*!
6978  * This method returns a newly created DataArrayInt instance.
6979  * This method retrieves cell ids in [begin,end) that have the type 'type'.
6980  */
6981 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6982 {
6983   checkFullyDefined();
6984   const int *conn=_nodal_connec->getConstPointer();
6985   const int *connIndex=_nodal_connec_index->getConstPointer();
6986   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6987   for(const int *w=begin;w!=end;w++)
6988     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6989       ret->pushBackSilent(*w);
6990   return ret.retn();
6991 }
6992
6993 /*!
6994  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6995  * are in [0:getNumberOfCells())
6996  */
6997 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6998 {
6999   checkFullyDefined();
7000   const int *conn=_nodal_connec->getConstPointer();
7001   const int *connI=_nodal_connec_index->getConstPointer();
7002   int nbOfCells=getNumberOfCells();
7003   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
7004   int *tmp=new int[nbOfCells];
7005   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7006     {
7007       int j=0;
7008       for(const int *i=connI;i!=connI+nbOfCells;i++)
7009         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7010           tmp[std::distance(connI,i)]=j++;
7011     }
7012   DataArrayInt *ret=DataArrayInt::New();
7013   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7014   ret->copyStringInfoFrom(*da);
7015   int *retPtr=ret->getPointer();
7016   const int *daPtr=da->getConstPointer();
7017   int nbOfElems=da->getNbOfElems();
7018   for(int k=0;k<nbOfElems;k++)
7019     retPtr[k]=tmp[daPtr[k]];
7020   delete [] tmp;
7021   return ret;
7022 }
7023
7024 /*!
7025  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7026  * This method \b works \b for mesh sorted by type.
7027  * cells whose ids is in 'idsPerGeoType' array.
7028  * This method conserves coords and name of mesh.
7029  */
7030 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7031 {
7032   std::vector<int> code=getDistributionOfTypes();
7033   std::size_t nOfTypesInThis=code.size()/3;
7034   int sz=0,szOfType=0;
7035   for(std::size_t i=0;i<nOfTypesInThis;i++)
7036     {
7037       if(code[3*i]!=type)
7038         sz+=code[3*i+1];
7039       else
7040         szOfType=code[3*i+1];
7041     }
7042   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7043     if(*work<0 || *work>=szOfType)
7044       {
7045         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7046         oss << ". It should be in [0," << szOfType << ") !";
7047         throw INTERP_KERNEL::Exception(oss.str().c_str());
7048       }
7049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7050   int *idsPtr=idsTokeep->getPointer();
7051   int offset=0;
7052   for(std::size_t i=0;i<nOfTypesInThis;i++)
7053     {
7054       if(code[3*i]!=type)
7055         for(int j=0;j<code[3*i+1];j++)
7056           *idsPtr++=offset+j;
7057       else
7058         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7059       offset+=code[3*i+1];
7060     }
7061   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7062   ret->copyTinyInfoFrom(this);
7063   return ret.retn();
7064 }
7065
7066 /*!
7067  * This method returns a vector of size 'this->getNumberOfCells()'.
7068  * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
7069  */
7070 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7071 {
7072   int ncell=getNumberOfCells();
7073   std::vector<bool> ret(ncell);
7074   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7075   const int *c=getNodalConnectivity()->getConstPointer();
7076   for(int i=0;i<ncell;i++)
7077     {
7078       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7079       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7080       ret[i]=cm.isQuadratic();
7081     }
7082   return ret;
7083 }
7084
7085 /*!
7086  * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
7087  */
7088 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7089 {
7090   if(other->getType()!=UNSTRUCTURED)
7091     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7092   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7093   return MergeUMeshes(this,otherC);
7094 }
7095
7096 /*!
7097  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7098  * computed by averaging coordinates of cell nodes, so this method is not a right
7099  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7100  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7101  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7102  *          components. The caller is to delete this array using decrRef() as it is
7103  *          no more needed.
7104  *  \throw If the coordinates array is not set.
7105  *  \throw If the nodal connectivity of cells is not defined.
7106  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7107  */
7108 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7109 {
7110   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7111   int spaceDim=getSpaceDimension();
7112   int nbOfCells=getNumberOfCells();
7113   ret->alloc(nbOfCells,spaceDim);
7114   ret->copyStringInfoFrom(*getCoords());
7115   double *ptToFill=ret->getPointer();
7116   const int *nodal=_nodal_connec->getConstPointer();
7117   const int *nodalI=_nodal_connec_index->getConstPointer();
7118   const double *coor=_coords->getConstPointer();
7119   for(int i=0;i<nbOfCells;i++)
7120     {
7121       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7122       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7123       ptToFill+=spaceDim;
7124     }
7125   return ret.retn();
7126 }
7127
7128 /*!
7129  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7130  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7131  * 
7132  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7133  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7134  * 
7135  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7136  * \throw If \a this is not fully defined (coordinates and connectivity)
7137  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7138  */
7139 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7140 {
7141   checkFullyDefined();
7142   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7143   int spaceDim=getSpaceDimension();
7144   int nbOfCells=getNumberOfCells();
7145   int nbOfNodes=getNumberOfNodes();
7146   ret->alloc(nbOfCells,spaceDim);
7147   double *ptToFill=ret->getPointer();
7148   const int *nodal=_nodal_connec->getConstPointer();
7149   const int *nodalI=_nodal_connec_index->getConstPointer();
7150   const double *coor=_coords->getConstPointer();
7151   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7152     {
7153       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7154       std::fill(ptToFill,ptToFill+spaceDim,0.);
7155       if(type!=INTERP_KERNEL::NORM_POLYHED)
7156         {
7157           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7158             {
7159               if(*conn>=0 && *conn<nbOfNodes)
7160                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7161               else
7162                 {
7163                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7164                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7165                 }
7166             }
7167           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7168           if(nbOfNodesInCell>0)
7169             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7170           else
7171             {
7172               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7173               throw INTERP_KERNEL::Exception(oss.str().c_str());
7174             }
7175         }
7176       else
7177         {
7178           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7179           s.erase(-1);
7180           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7181             {
7182               if(*it>=0 && *it<nbOfNodes)
7183                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7184               else
7185                 {
7186                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7187                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7188                 }
7189             }
7190           if(!s.empty())
7191             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7192           else
7193             {
7194               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7195               throw INTERP_KERNEL::Exception(oss.str().c_str());
7196             }
7197         }
7198     }
7199   return ret.retn();
7200 }
7201
7202 /*!
7203  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7204  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7205  * are specified via an array of cell ids. 
7206  *  \warning Validity of the specified cell ids is not checked! 
7207  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7208  *  \param [in] begin - an array of cell ids of interest.
7209  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7210  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7211  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7212  *          caller is to delete this array using decrRef() as it is no more needed. 
7213  *  \throw If the coordinates array is not set.
7214  *  \throw If the nodal connectivity of cells is not defined.
7215  *
7216  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7217  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7218  */
7219 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7220 {
7221   DataArrayDouble *ret=DataArrayDouble::New();
7222   int spaceDim=getSpaceDimension();
7223   int nbOfTuple=(int)std::distance(begin,end);
7224   ret->alloc(nbOfTuple,spaceDim);
7225   double *ptToFill=ret->getPointer();
7226   double *tmp=new double[spaceDim];
7227   const int *nodal=_nodal_connec->getConstPointer();
7228   const int *nodalI=_nodal_connec_index->getConstPointer();
7229   const double *coor=_coords->getConstPointer();
7230   for(const int *w=begin;w!=end;w++)
7231     {
7232       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7233       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7234       ptToFill+=spaceDim;
7235     }
7236   delete [] tmp;
7237   return ret;
7238 }
7239
7240 /*!
7241  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7242  * 
7243  */
7244 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7245 {
7246   if(!da)
7247     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7248   da->checkAllocated();
7249   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7250   ret->setCoords(da);
7251   int nbOfTuples=da->getNumberOfTuples();
7252   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7254   c->alloc(2*nbOfTuples,1);
7255   cI->alloc(nbOfTuples+1,1);
7256   int *cp=c->getPointer();
7257   int *cip=cI->getPointer();
7258   *cip++=0;
7259   for(int i=0;i<nbOfTuples;i++)
7260     {
7261       *cp++=INTERP_KERNEL::NORM_POINT1;
7262       *cp++=i;
7263       *cip++=2*(i+1);
7264     }
7265   ret->setConnectivity(c,cI,true);
7266   return ret.retn();
7267 }
7268 /*!
7269  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7270  * Cells and nodes of
7271  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7272  *  \param [in] mesh1 - the first mesh.
7273  *  \param [in] mesh2 - the second mesh.
7274  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7275  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7276  *          is no more needed.
7277  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7278  *  \throw If the coordinates array is not set in none of the meshes.
7279  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7280  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7281  */
7282 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7283 {
7284   std::vector<const MEDCouplingUMesh *> tmp(2);
7285   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7286   return MergeUMeshes(tmp);
7287 }
7288
7289 /*!
7290  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7291  * Cells and nodes of
7292  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7293  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7294  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7295  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7296  *          is no more needed.
7297  *  \throw If \a a.size() == 0.
7298  *  \throw If \a a[ *i* ] == NULL.
7299  *  \throw If the coordinates array is not set in none of the meshes.
7300  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7301  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7302 */
7303 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7304 {
7305   std::size_t sz=a.size();
7306   if(sz==0)
7307     return MergeUMeshesLL(a);
7308   for(std::size_t ii=0;ii<sz;ii++)
7309     if(!a[ii])
7310       {
7311         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7312         throw INTERP_KERNEL::Exception(oss.str().c_str());
7313       }
7314   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7315   std::vector< const MEDCouplingUMesh * > aa(sz);
7316   int spaceDim=-3;
7317   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7318     {
7319       const MEDCouplingUMesh *cur=a[i];
7320       const DataArrayDouble *coo=cur->getCoords();
7321       if(coo)
7322         spaceDim=coo->getNumberOfComponents();
7323     }
7324   if(spaceDim==-3)
7325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7326   for(std::size_t i=0;i<sz;i++)
7327     {
7328       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7329       aa[i]=bb[i];
7330     }
7331   return MergeUMeshesLL(aa);
7332 }
7333
7334 /// @cond INTERNAL
7335
7336 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7337 {
7338   if(a.empty())
7339     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7340   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7341   int meshDim=(*it)->getMeshDimension();
7342   int nbOfCells=(*it)->getNumberOfCells();
7343   int meshLgth=(*it++)->getMeshLength();
7344   for(;it!=a.end();it++)
7345     {
7346       if(meshDim!=(*it)->getMeshDimension())
7347         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7348       nbOfCells+=(*it)->getNumberOfCells();
7349       meshLgth+=(*it)->getMeshLength();
7350     }
7351   std::vector<const MEDCouplingPointSet *> aps(a.size());
7352   std::copy(a.begin(),a.end(),aps.begin());
7353   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7354   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7355   ret->setCoords(pts);
7356   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7357   c->alloc(meshLgth,1);
7358   int *cPtr=c->getPointer();
7359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7360   cI->alloc(nbOfCells+1,1);
7361   int *cIPtr=cI->getPointer();
7362   *cIPtr++=0;
7363   int offset=0;
7364   int offset2=0;
7365   for(it=a.begin();it!=a.end();it++)
7366     {
7367       int curNbOfCell=(*it)->getNumberOfCells();
7368       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7369       const int *curC=(*it)->_nodal_connec->getConstPointer();
7370       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7371       for(int j=0;j<curNbOfCell;j++)
7372         {
7373           const int *src=curC+curCI[j];
7374           *cPtr++=*src++;
7375           for(;src!=curC+curCI[j+1];src++,cPtr++)
7376             {
7377               if(*src!=-1)
7378                 *cPtr=*src+offset2;
7379               else
7380                 *cPtr=-1;
7381             }
7382         }
7383       offset+=curCI[curNbOfCell];
7384       offset2+=(*it)->getNumberOfNodes();
7385     }
7386   //
7387   ret->setConnectivity(c,cI,true);
7388   return ret.retn();
7389 }
7390
7391 /// @endcond
7392
7393 /*!
7394  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7395  * dimension and sharing the node coordinates array.
7396  * All cells of the first mesh precede all cells of the second mesh
7397  * within the result mesh. 
7398  *  \param [in] mesh1 - the first mesh.
7399  *  \param [in] mesh2 - the second mesh.
7400  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7401  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7402  *          is no more needed.
7403  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7404  *  \throw If the meshes do not share the node coordinates array.
7405  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7406  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7407  */
7408 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7409 {
7410   std::vector<const MEDCouplingUMesh *> tmp(2);
7411   tmp[0]=mesh1; tmp[1]=mesh2;
7412   return MergeUMeshesOnSameCoords(tmp);
7413 }
7414
7415 /*!
7416  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7417  * dimension and sharing the node coordinates array.
7418  * All cells of the *i*-th mesh precede all cells of the
7419  * (*i*+1)-th mesh within the result mesh.
7420  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7421  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7422  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7423  *          is no more needed.
7424  *  \throw If \a a.size() == 0.
7425  *  \throw If \a a[ *i* ] == NULL.
7426  *  \throw If the meshes do not share the node coordinates array.
7427  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7428  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7429  */
7430 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7431 {
7432   if(meshes.empty())
7433     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7434   for(std::size_t ii=0;ii<meshes.size();ii++)
7435     if(!meshes[ii])
7436       {
7437         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7438         throw INTERP_KERNEL::Exception(oss.str().c_str());
7439       }
7440   const DataArrayDouble *coords=meshes.front()->getCoords();
7441   int meshDim=meshes.front()->getMeshDimension();
7442   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7443   int meshLgth=0;
7444   int meshIndexLgth=0;
7445   for(;iter!=meshes.end();iter++)
7446     {
7447       if(coords!=(*iter)->getCoords())
7448         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7449       if(meshDim!=(*iter)->getMeshDimension())
7450         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7451       meshLgth+=(*iter)->getMeshLength();
7452       meshIndexLgth+=(*iter)->getNumberOfCells();
7453     }
7454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7455   nodal->alloc(meshLgth,1);
7456   int *nodalPtr=nodal->getPointer();
7457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7458   nodalIndex->alloc(meshIndexLgth+1,1);
7459   int *nodalIndexPtr=nodalIndex->getPointer();
7460   int offset=0;
7461   for(iter=meshes.begin();iter!=meshes.end();iter++)
7462     {
7463       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7464       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7465       int nbOfCells=(*iter)->getNumberOfCells();
7466       int meshLgth2=(*iter)->getMeshLength();
7467       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7468       if(iter!=meshes.begin())
7469         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7470       else
7471         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7472       offset+=meshLgth2;
7473     }
7474   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7475   ret->setName("merge");
7476   ret->setMeshDimension(meshDim);
7477   ret->setConnectivity(nodal,nodalIndex,true);
7478   ret->setCoords(coords);
7479   return ret;
7480 }
7481
7482 /*!
7483  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7484  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7485  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7486  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7487  * New" mode are returned for each input mesh.
7488  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7489  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7490  *          valid values [0,1,2], see zipConnectivityTraducer().
7491  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7492  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7493  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7494  *          no more needed.
7495  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7496  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7497  *          is no more needed.
7498  *  \throw If \a meshes.size() == 0.
7499  *  \throw If \a meshes[ *i* ] == NULL.
7500  *  \throw If the meshes do not share the node coordinates array.
7501  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7502  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7503  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7504  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7505  */
7506 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7507 {
7508   //All checks are delegated to MergeUMeshesOnSameCoords
7509   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7511   corr.resize(meshes.size());
7512   std::size_t nbOfMeshes=meshes.size();
7513   int offset=0;
7514   const int *o2nPtr=o2n->getConstPointer();
7515   for(std::size_t i=0;i<nbOfMeshes;i++)
7516     {
7517       DataArrayInt *tmp=DataArrayInt::New();
7518       int curNbOfCells=meshes[i]->getNumberOfCells();
7519       tmp->alloc(curNbOfCells,1);
7520       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7521       offset+=curNbOfCells;
7522       tmp->setName(meshes[i]->getName());
7523       corr[i]=tmp;
7524     }
7525   return ret.retn();
7526 }
7527
7528 /*!
7529  * Makes all given meshes share the nodal connectivity array. The common connectivity
7530  * array is created by concatenating the connectivity arrays of all given meshes. All
7531  * the given meshes must be of the same space dimension but dimension of cells **can
7532  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7533  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7534  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7535  *  \param [in,out] meshes - a vector of meshes to update.
7536  *  \throw If any of \a meshes is NULL.
7537  *  \throw If the coordinates array is not set in any of \a meshes.
7538  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7539  *  \throw If \a meshes are of different space dimension.
7540  */
7541 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7542 {
7543   std::size_t sz=meshes.size();
7544   if(sz==0 || sz==1)
7545     return;
7546   std::vector< const DataArrayDouble * > coords(meshes.size());
7547   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7548   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7549     {
7550       if((*it))
7551         {
7552           (*it)->checkConnectivityFullyDefined();
7553           const DataArrayDouble *coo=(*it)->getCoords();
7554           if(coo)
7555             *it2=coo;
7556           else
7557             {
7558               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7559               oss << " has no coordinate array defined !";
7560               throw INTERP_KERNEL::Exception(oss.str().c_str());
7561             }
7562         }
7563       else
7564         {
7565           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7566           oss << " is null !";
7567           throw INTERP_KERNEL::Exception(oss.str().c_str());
7568         }
7569     }
7570   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7571   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7572   int offset=(*it)->getNumberOfNodes();
7573   (*it++)->setCoords(res);
7574   for(;it!=meshes.end();it++)
7575     {
7576       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7577       (*it)->setCoords(res);
7578       (*it)->shiftNodeNumbersInConn(offset);
7579       offset+=oldNumberOfNodes;
7580     }
7581 }
7582
7583 /*!
7584  * Merges nodes coincident with a given precision within all given meshes that share
7585  * the nodal connectivity array. The given meshes **can be of different** mesh
7586  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7587  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7588  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7589  *  \param [in,out] meshes - a vector of meshes to update.
7590  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7591  *  \throw If any of \a meshes is NULL.
7592  *  \throw If the \a meshes do not share the same node coordinates array.
7593  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7594  */
7595 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7596 {
7597   if(meshes.empty())
7598     return ;
7599   std::set<const DataArrayDouble *> s;
7600   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7601     {
7602       if(*it)
7603         s.insert((*it)->getCoords());
7604       else
7605         {
7606           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 !";
7607           throw INTERP_KERNEL::Exception(oss.str().c_str());
7608         }
7609     }
7610   if(s.size()!=1)
7611     {
7612       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 !";
7613       throw INTERP_KERNEL::Exception(oss.str().c_str());
7614     }
7615   const DataArrayDouble *coo=*(s.begin());
7616   if(!coo)
7617     return;
7618   //
7619   DataArrayInt *comm,*commI;
7620   coo->findCommonTuples(eps,-1,comm,commI);
7621   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7622   int oldNbOfNodes=coo->getNumberOfTuples();
7623   int newNbOfNodes;
7624   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7625   if(oldNbOfNodes==newNbOfNodes)
7626     return ;
7627   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7628   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7629     {
7630       (*it)->renumberNodesInConn(o2n->getConstPointer());
7631       (*it)->setCoords(newCoords);
7632     } 
7633 }
7634
7635 /*!
7636  * 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.
7637  * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7638  * @param isQuad specifies the policy of connectivity.
7639  * @ret in/out parameter in which the result will be append
7640  */
7641 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7642 {
7643   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7644   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7645   ret.push_back(cm.getExtrudedType());
7646   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7647   switch(flatType)
7648     {
7649     case INTERP_KERNEL::NORM_POINT1:
7650       {
7651         ret.push_back(connBg[1]);
7652         ret.push_back(connBg[1]+nbOfNodesPerLev);
7653         break;
7654       }
7655     case INTERP_KERNEL::NORM_SEG2:
7656       {
7657         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7658         ret.insert(ret.end(),conn,conn+4);
7659         break;
7660       }
7661     case INTERP_KERNEL::NORM_SEG3:
7662       {
7663         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7664         ret.insert(ret.end(),conn,conn+8);
7665         break;
7666       }
7667     case INTERP_KERNEL::NORM_QUAD4:
7668       {
7669         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7670         ret.insert(ret.end(),conn,conn+8);
7671         break;
7672       }
7673     case INTERP_KERNEL::NORM_TRI3:
7674       {
7675         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7676         ret.insert(ret.end(),conn,conn+6);
7677         break;
7678       }
7679     case INTERP_KERNEL::NORM_TRI6:
7680       {
7681         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,
7682                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7683         ret.insert(ret.end(),conn,conn+15);
7684         break;
7685       }
7686     case INTERP_KERNEL::NORM_QUAD8:
7687       {
7688         int conn[20]={
7689           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7690           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7691           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7692         };
7693         ret.insert(ret.end(),conn,conn+20);
7694         break;
7695       }
7696     case INTERP_KERNEL::NORM_POLYGON:
7697       {
7698         std::back_insert_iterator< std::vector<int> > ii(ret);
7699         std::copy(connBg+1,connEnd,ii);
7700         *ii++=-1;
7701         std::reverse_iterator<const int *> rConnBg(connEnd);
7702         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7703         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7704         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7705         for(std::size_t i=0;i<nbOfRadFaces;i++)
7706           {
7707             *ii++=-1;
7708             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7709             std::copy(conn,conn+4,ii);
7710           }
7711         break;
7712       }
7713     default:
7714       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7715     }
7716 }
7717
7718 /*!
7719  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
7720  */
7721 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7722 {
7723   double v[3]={0.,0.,0.};
7724   std::size_t sz=std::distance(begin,end);
7725   if(isQuadratic)
7726     sz/=2;
7727   for(std::size_t i=0;i<sz;i++)
7728     {
7729       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];
7730       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7731       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7732     }
7733   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7734 }
7735
7736 /*!
7737  * The polyhedron is specfied by its connectivity nodes in [begin,end).
7738  */
7739 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7740 {
7741   std::vector<std::pair<int,int> > edges;
7742   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7743   const int *bgFace=begin;
7744   for(std::size_t i=0;i<nbOfFaces;i++)
7745     {
7746       const int *endFace=std::find(bgFace+1,end,-1);
7747       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7748       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7749         {
7750           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7751           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7752             return false;
7753           edges.push_back(p1);
7754         }
7755       bgFace=endFace+1;
7756     }
7757   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7758 }
7759
7760 /*!
7761  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
7762  */
7763 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7764 {
7765   double vec0[3],vec1[3];
7766   std::size_t sz=std::distance(begin,end);
7767   if(sz%2!=0)
7768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7769   int nbOfNodes=(int)sz/2;
7770   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7771   const double *pt0=coords+3*begin[0];
7772   const double *pt1=coords+3*begin[nbOfNodes];
7773   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7774   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7775 }
7776
7777 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7778 {
7779   std::size_t sz=std::distance(begin,end);
7780   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7781   std::size_t nbOfNodes(sz/2);
7782   std::copy(begin,end,(int *)tmp);
7783   for(std::size_t j=1;j<nbOfNodes;j++)
7784     {
7785       begin[j]=tmp[nbOfNodes-j];
7786       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7787     }
7788 }
7789
7790 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7791 {
7792   std::size_t sz=std::distance(begin,end);
7793   if(sz!=4)
7794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7795   double vec0[3],vec1[3];
7796   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7797   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]; 
7798   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;
7799 }
7800
7801 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7802 {
7803   std::size_t sz=std::distance(begin,end);
7804   if(sz!=5)
7805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7806   double vec0[3];
7807   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7808   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7809   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7810 }
7811
7812 /*!
7813  * 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) 
7814  * 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
7815  * a 2D space.
7816  *
7817  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7818  * \param [in] coords the coordinates with nb of components exactly equal to 3
7819  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7820  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7821  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7822  */
7823 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7824 {
7825   int nbFaces=std::count(begin+1,end,-1)+1;
7826   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7827   double *vPtr=v->getPointer();
7828   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7829   double *pPtr=p->getPointer();
7830   const int *stFaceConn=begin+1;
7831   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7832     {
7833       const int *endFaceConn=std::find(stFaceConn,end,-1);
7834       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7835       stFaceConn=endFaceConn+1;
7836     }
7837   pPtr=p->getPointer(); vPtr=v->getPointer();
7838   DataArrayInt *comm1=0,*commI1=0;
7839   v->findCommonTuples(eps,-1,comm1,commI1);
7840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7841   const int *comm1Ptr=comm1->getConstPointer();
7842   const int *commI1Ptr=commI1->getConstPointer();
7843   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7844   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7845   //
7846   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7847   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7848   mm->finishInsertingCells();
7849   //
7850   for(int i=0;i<nbOfGrps1;i++)
7851     {
7852       int vecId=comm1Ptr[commI1Ptr[i]];
7853       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7854       DataArrayInt *comm2=0,*commI2=0;
7855       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7856       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7857       const int *comm2Ptr=comm2->getConstPointer();
7858       const int *commI2Ptr=commI2->getConstPointer();
7859       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7860       for(int j=0;j<nbOfGrps2;j++)
7861         {
7862           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7863             {
7864               res->insertAtTheEnd(begin,end);
7865               res->pushBackSilent(-1);
7866             }
7867           else
7868             {
7869               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7870               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7871               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7872               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7873               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7874               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7875               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7876               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7877               const int *idsNodePtr=idsNode->getConstPointer();
7878               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];
7879               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7880               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7881               if(std::abs(norm)>eps)
7882                 {
7883                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7884                   mm3->rotate(center,vec,angle);
7885                 }
7886               mm3->changeSpaceDimension(2);
7887               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7888               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7889               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7890               int nbOfCells=mm4->getNumberOfCells();
7891               for(int k=0;k<nbOfCells;k++)
7892                 {
7893                   int l=0;
7894                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7895                     res->pushBackSilent(idsNodePtr[*work]);
7896                   res->pushBackSilent(-1);
7897                 }
7898             }
7899         }
7900     }
7901   res->popBackSilent();
7902 }
7903
7904 /*!
7905  * 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
7906  * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
7907  * 
7908  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7909  * \param [in] coords coordinates expected to have 3 components.
7910  * \param [in] begin start of the nodal connectivity of the face.
7911  * \param [in] end end of the nodal connectivity (excluded) of the face.
7912  * \param [out] v the normalized vector of size 3
7913  * \param [out] p the pos of plane
7914  */
7915 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7916 {
7917   std::size_t nbPoints=std::distance(begin,end);
7918   if(nbPoints<3)
7919     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7920   double vec[3];
7921   std::size_t j=0;
7922   bool refFound=false;
7923   for(;j<nbPoints-1 && !refFound;j++)
7924     {
7925       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7926       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7927       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7928       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7929       if(norm>eps)
7930         {
7931           refFound=true;
7932           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7933         }
7934     }
7935   for(std::size_t i=j;i<nbPoints-1;i++)
7936     {
7937       double curVec[3];
7938       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7939       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7940       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7941       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7942       if(norm<eps)
7943         continue;
7944       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7945       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];
7946       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7947       if(norm>eps)
7948         {
7949           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7950           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7951           return ;
7952         }
7953     }
7954   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7955 }
7956
7957 /*!
7958  * This method tries to obtain a well oriented polyhedron.
7959  * If the algorithm fails, an exception will be thrown.
7960  */
7961 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7962 {
7963   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7964   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7965   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7966   isPerm[0]=true;
7967   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7968   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7969   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7970   //
7971   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7972     {
7973       bgFace=begin;
7974       std::size_t smthChanged=0;
7975       for(std::size_t i=0;i<nbOfFaces;i++)
7976         {
7977           endFace=std::find(bgFace+1,end,-1);
7978           nbOfEdgesInFace=std::distance(bgFace,endFace);
7979           if(!isPerm[i])
7980             {
7981               bool b;
7982               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7983                 {
7984                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7985                   std::pair<int,int> p2(p1.second,p1.first);
7986                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7987                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7988                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7989                 }
7990               if(isPerm[i])
7991                 { 
7992                   if(!b)
7993                     std::reverse(bgFace+1,endFace);
7994                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7995                     {
7996                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7997                       std::pair<int,int> p2(p1.second,p1.first);
7998                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7999                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8000                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8001                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8002                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8003                       if(it!=edgesOK.end())
8004                         {
8005                           edgesOK.erase(it);
8006                           edgesFinished.push_back(p1);
8007                         }
8008                       else
8009                         edgesOK.push_back(p1);
8010                     }
8011                 }
8012             }
8013           bgFace=endFace+1;
8014         }
8015       if(smthChanged==0)
8016         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8017     }
8018   if(!edgesOK.empty())
8019     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8020   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8021     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8022       bgFace=begin;
8023       for(std::size_t i=0;i<nbOfFaces;i++)
8024         {
8025           endFace=std::find(bgFace+1,end,-1);
8026           std::reverse(bgFace+1,endFace);
8027           bgFace=endFace+1;
8028         }
8029     }
8030 }
8031
8032 /*!
8033  * This method makes the assumption spacedimension == meshdimension == 2.
8034  * This method works only for linear cells.
8035  * 
8036  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8037  */
8038 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
8039 {
8040   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8041     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8042   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8044   int nbOfNodesExpected=m->getNumberOfNodes();
8045   if(m->getNumberOfCells()!=nbOfNodesExpected)
8046     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8048   const int *n2oPtr=n2o->getConstPointer();
8049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8050   m->getReverseNodalConnectivity(revNodal,revNodalI);
8051   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8052   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8053   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8055   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8056   if(nbOfNodesExpected<1)
8057     return ret.retn();
8058   int prevCell=0;
8059   int prevNode=nodalPtr[nodalIPtr[0]+1];
8060   *work++=n2oPtr[prevNode];
8061   for(int i=1;i<nbOfNodesExpected;i++)
8062     {
8063       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8064         {
8065           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8066           conn.erase(prevNode);
8067           if(conn.size()==1)
8068             {
8069               int curNode=*(conn.begin());
8070               *work++=n2oPtr[curNode];
8071               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8072               shar.erase(prevCell);
8073               if(shar.size()==1)
8074                 {
8075                   prevCell=*(shar.begin());
8076                   prevNode=curNode;
8077                 }
8078               else
8079                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8080             }
8081           else
8082             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8083         }
8084       else
8085         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8086     }
8087   return ret.retn();
8088 }
8089
8090 /*!
8091  * This method makes the assumption spacedimension == meshdimension == 3.
8092  * This method works only for linear cells.
8093  * 
8094  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8095  */
8096 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8097 {
8098   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8099     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8100   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8101   const int *conn=m->getNodalConnectivity()->getConstPointer();
8102   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8103   int nbOfCells=m->getNumberOfCells();
8104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8105   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8106   if(nbOfCells<1)
8107     return ret.retn();
8108   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8109   for(int i=1;i<nbOfCells;i++)
8110     {
8111       *work++=-1;
8112       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8113     }
8114   return ret.retn();
8115 }
8116
8117 /*!
8118  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8119  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8120  */
8121 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8122 {
8123   double *w=zipFrmt;
8124   if(spaceDim==3)
8125     for(int i=0;i<nbOfNodesInCell;i++)
8126       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8127   else if(spaceDim==2)
8128     {
8129       for(int i=0;i<nbOfNodesInCell;i++)
8130         {
8131           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8132           *w++=0.;
8133         }
8134     }
8135   else
8136     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8137 }
8138
8139 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8140 {
8141   int nbOfCells=getNumberOfCells();
8142   if(nbOfCells<=0)
8143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8144   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};
8145   ofs << "  <" << getVTKDataSetType() << ">\n";
8146   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8147   ofs << "      <PointData>\n" << pointData << std::endl;
8148   ofs << "      </PointData>\n";
8149   ofs << "      <CellData>\n" << cellData << std::endl;
8150   ofs << "      </CellData>\n";
8151   ofs << "      <Points>\n";
8152   if(getSpaceDimension()==3)
8153     _coords->writeVTK(ofs,8,"Points");
8154   else
8155     {
8156       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8157       coo->writeVTK(ofs,8,"Points");
8158     }
8159   ofs << "      </Points>\n";
8160   ofs << "      <Cells>\n";
8161   const int *cPtr=_nodal_connec->getConstPointer();
8162   const int *cIPtr=_nodal_connec_index->getConstPointer();
8163   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8167   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8168   int szFaceOffsets=0,szConn=0;
8169   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8170     {
8171       *w2=cPtr[cIPtr[i]];
8172       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8173         {
8174           *w1=-1;
8175           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8176           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8177         }
8178       else
8179         {
8180           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8181           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8182           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8183           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8184           w4=std::copy(c.begin(),c.end(),w4);
8185         }
8186     }
8187   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8188   types->writeVTK(ofs,8,"UInt8","types");
8189   offsets->writeVTK(ofs,8,"Int32","offsets");
8190   if(szFaceOffsets!=0)
8191     {//presence of Polyhedra
8192       connectivity->reAlloc(szConn);
8193       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8194       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8195       w1=faces->getPointer();
8196       for(int i=0;i<nbOfCells;i++)
8197         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8198           {
8199             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8200             *w1++=nbFaces;
8201             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8202             for(int j=0;j<nbFaces;j++)
8203               {
8204                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8205                 *w1++=(int)std::distance(w6,w5);
8206                 w1=std::copy(w6,w5,w1);
8207                 w6=w5+1;
8208               }
8209           }
8210       faces->writeVTK(ofs,8,"Int32","faces");
8211     }
8212   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8213   ofs << "      </Cells>\n";
8214   ofs << "    </Piece>\n";
8215   ofs << "  </" << getVTKDataSetType() << ">\n";
8216 }
8217
8218 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8219 {
8220   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8221   if(_mesh_dim==-2)
8222     { stream << " Not set !"; return ; }
8223   stream << " Mesh dimension : " << _mesh_dim << ".";
8224   if(_mesh_dim==-1)
8225     return ;
8226   if(!_coords)
8227     { stream << " No coordinates set !"; return ; }
8228   if(!_coords->isAllocated())
8229     { stream << " Coordinates set but not allocated !"; return ; }
8230   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8231   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8232   if(!_nodal_connec_index)
8233     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8234   if(!_nodal_connec_index->isAllocated())
8235     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8236   int lgth=_nodal_connec_index->getNumberOfTuples();
8237   int cpt=_nodal_connec_index->getNumberOfComponents();
8238   if(cpt!=1 || lgth<1)
8239     return ;
8240   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8241 }
8242
8243 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8244 {
8245   return std::string("UnstructuredGrid");
8246 }
8247
8248 /*!
8249  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8250  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8251  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8252  * meshes.
8253  *  \param [in] m1 - the first input mesh which is a partitioned object.
8254  *  \param [in] m2 - the second input mesh which is a partition tool.
8255  *  \param [in] eps - precision used to detect coincident mesh entities.
8256  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8257  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8258  *         this array using decrRef() as it is no more needed.
8259  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8260  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8261  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8262  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8263  *         it is no more needed.  
8264  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8265  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8266  *         is no more needed.  
8267  *  \throw If the coordinates array is not set in any of the meshes.
8268  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8269  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8270  */
8271 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8272 {
8273   m1->checkFullyDefined();
8274   m2->checkFullyDefined();
8275   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8276     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8277   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8278   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8279   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8280   std::vector<double> addCoo,addCoordsQuadratic;
8281   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8282   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8283   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8284                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8285   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8287   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8288   std::vector< std::vector<int> > intersectEdge2;
8289   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8290   subDiv2.clear(); dd5=0; dd6=0;
8291   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8292   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8293   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8294                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8295   //
8296   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8297   addCooDa->alloc((int)(addCoo.size())/2,2);
8298   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8299   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8300   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8301   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8302   std::vector<const DataArrayDouble *> coordss(4);
8303   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8304   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8305   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8310   ret->setConnectivity(conn,connI,true);
8311   ret->setCoords(coo);
8312   cellNb1=c1.retn(); cellNb2=c2.retn();
8313   return ret.retn();
8314 }
8315
8316 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8317                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8318                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8319                                                          const std::vector<double>& addCoords,
8320                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8321 {
8322   static const int SPACEDIM=2;
8323   std::vector<double> bbox1,bbox2;
8324   const double *coo1=m1->getCoords()->getConstPointer();
8325   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8326   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8327   int offset1=m1->getNumberOfNodes();
8328   const double *coo2=m2->getCoords()->getConstPointer();
8329   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8330   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8331   int offset2=offset1+m2->getNumberOfNodes();
8332   int offset3=offset2+((int)addCoords.size())/2;
8333   m1->getBoundingBoxForBBTree(bbox1);
8334   m2->getBoundingBoxForBBTree(bbox2);
8335   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8336   int ncell1=m1->getNumberOfCells();
8337   crI.push_back(0);
8338   for(int i=0;i<ncell1;i++)
8339     {
8340       std::vector<int> candidates2;
8341       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8342       std::map<INTERP_KERNEL::Node *,int> mapp;
8343       std::map<int,INTERP_KERNEL::Node *> mappRev;
8344       INTERP_KERNEL::QuadraticPolygon pol1;
8345       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8346       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8347       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8348       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8349                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8350       //
8351       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
8352       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8353       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8354       for(it1.first();!it1.finished();it1.next())
8355         edges1.insert(it1.current()->getPtr());
8356       //
8357       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8358       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8359       int ii=0;
8360       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8361         {
8362           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8363           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8364           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8365           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8366                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8367         }
8368       ii=0;
8369       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8370         {
8371           pol1.initLocationsWithOther(pol2s[ii]);
8372           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8373           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8374           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8375         }
8376       if(!edges1.empty())
8377         {
8378           try
8379             {
8380               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8381             }
8382           catch(INTERP_KERNEL::Exception& e)
8383             {
8384               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();
8385               throw INTERP_KERNEL::Exception(oss.str().c_str());
8386             }
8387         }
8388       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8389         (*it).second->decrRef();
8390     }
8391 }
8392
8393 /*!
8394  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8395  * 
8396  */
8397 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8398                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8399                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8400                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8401                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8402 {
8403   static const int SPACEDIM=2;
8404   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8405   desc2=DataArrayInt::New();
8406   descIndx2=DataArrayInt::New();
8407   revDesc2=DataArrayInt::New();
8408   revDescIndx2=DataArrayInt::New();
8409   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8410   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8411   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8412   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8413   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8414   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8415   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8416   std::vector<double> bbox1,bbox2;
8417   m1Desc->getBoundingBoxForBBTree(bbox1);
8418   m2Desc->getBoundingBoxForBBTree(bbox2);
8419   int ncell1=m1Desc->getNumberOfCells();
8420   int ncell2=m2Desc->getNumberOfCells();
8421   intersectEdge1.resize(ncell1);
8422   colinear2.resize(ncell2);
8423   subDiv2.resize(ncell2);
8424   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8425   std::vector<int> candidates1(1);
8426   int offset1=m1->getNumberOfNodes();
8427   int offset2=offset1+m2->getNumberOfNodes();
8428   for(int i=0;i<ncell1;i++)
8429     {
8430       std::vector<int> candidates2;
8431       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8432       if(!candidates2.empty())
8433         {
8434           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8435           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8436           candidates1[0]=i;
8437           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8438           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8439           delete pol2;
8440           delete pol1;
8441         }
8442       else
8443         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8444     }
8445   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8446   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8447 }
8448
8449 /*!
8450  * This method performs the 2nd step of Partition of 2D mesh.
8451  * This method has 4 inputs :
8452  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8453  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8454  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8455  * 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'
8456  * @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'
8457  * @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.
8458  * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8459  */
8460 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)
8461 {
8462   int offset1=m1->getNumberOfNodes();
8463   int ncell=m2->getNumberOfCells();
8464   const int *c=m2->getNodalConnectivity()->getConstPointer();
8465   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8466   const double *coo=m2->getCoords()->getConstPointer();
8467   const double *cooBis=m1->getCoords()->getConstPointer();
8468   int offset2=offset1+m2->getNumberOfNodes();
8469   intersectEdge.resize(ncell);
8470   for(int i=0;i<ncell;i++,cI++)
8471     {
8472       const std::vector<int>& divs=subDiv[i];
8473       int nnode=cI[1]-cI[0]-1;
8474       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8475       std::map<INTERP_KERNEL::Node *, int> mapp22;
8476       for(int j=0;j<nnode;j++)
8477         {
8478           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8479           int nnid=c[(*cI)+j+1];
8480           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8481           mapp22[nn]=nnid+offset1;
8482         }
8483       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8484       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8485         ((*it).second.first)->decrRef();
8486       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8487       std::map<INTERP_KERNEL::Node *,int> mapp3;
8488       for(std::size_t j=0;j<divs.size();j++)
8489         {
8490           int id=divs[j];
8491           INTERP_KERNEL::Node *tmp=0;
8492           if(id<offset1)
8493             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8494           else if(id<offset2)
8495             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8496           else
8497             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8498           addNodes[j]=tmp;
8499           mapp3[tmp]=id;
8500         }
8501       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8502       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8503         (*it)->decrRef();
8504       e->decrRef();
8505     }
8506 }
8507
8508 /*!
8509  * 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).
8510  * 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
8511  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8512  * @param cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8513  * @param nodesOnPlane, returns all the nodes that are on the plane.
8514  * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
8515  * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8516  * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
8517  * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8518  * @param desc is the descending connectivity 3DSurf->3DCurve
8519  * @param descIndx is the descending connectivity index 3DSurf->3DCurve
8520  * @param cut3DSuf input/output param.
8521  */
8522 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8523                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8524                                                    const int *desc, const int *descIndx, 
8525                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8526 {
8527   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8528   int nbOf3DSurfCell=(int)cut3DSurf.size();
8529   for(int i=0;i<nbOf3DSurfCell;i++)
8530     {
8531       std::vector<int> res;
8532       int offset=descIndx[i];
8533       int nbOfSeg=descIndx[i+1]-offset;
8534       for(int j=0;j<nbOfSeg;j++)
8535         {
8536           int edgeId=desc[offset+j];
8537           int status=cut3DCurve[edgeId];
8538           if(status!=-2)
8539             {
8540               if(status>-1)
8541                 res.push_back(status);
8542               else
8543                 {
8544                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8545                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8546                 }
8547             }
8548         }
8549       switch(res.size())
8550         {
8551         case 2:
8552           {
8553             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8554             break;
8555           }
8556         case 1:
8557         case 0:
8558           {
8559             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8560             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8561             if(res.size()==2)
8562               {
8563                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8564               }
8565             else
8566               {
8567                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8568               }
8569             break;
8570           }
8571         default:
8572           {// case when plane is on a multi colinear edge of a polyhedron
8573             if((int)res.size()==2*nbOfSeg)
8574               {
8575                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8576               }
8577             else
8578               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8579           }
8580         }
8581     }
8582 }
8583
8584 /*!
8585  * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8586  * 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).
8587  * 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
8588  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8589  * @param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8590  * @param desc is the descending connectivity 3D->3DSurf
8591  * @param descIndx is the descending connectivity index 3D->3DSurf
8592  */
8593 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8594                                                   const int *desc, const int *descIndx,
8595                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8596 {
8597   checkFullyDefined();
8598   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8600   const int *nodal3D=_nodal_connec->getConstPointer();
8601   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8602   int nbOfCells=getNumberOfCells();
8603   for(int i=0;i<nbOfCells;i++)
8604     {
8605       std::map<int, std::set<int> > m;
8606       int offset=descIndx[i];
8607       int nbOfFaces=descIndx[i+1]-offset;
8608       int start=-1;
8609       int end=-1;
8610       for(int j=0;j<nbOfFaces;j++)
8611         {
8612           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8613           if(p.first!=-1 && p.second!=-1)
8614             {
8615               if(p.first!=-2)
8616                 {
8617                   start=p.first; end=p.second;
8618                   m[p.first].insert(p.second);
8619                   m[p.second].insert(p.first);
8620                 }
8621               else
8622                 {
8623                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8624                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8625                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8626                   INTERP_KERNEL::NormalizedCellType cmsId;
8627                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8628                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8629                   for(unsigned k=0;k<nbOfNodesSon;k++)
8630                     {
8631                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8632                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8633                     }
8634                 }
8635             }
8636         }
8637       if(m.empty())
8638         continue;
8639       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8640       int prev=end;
8641       while(end!=start)
8642         {
8643           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8644           const std::set<int>& s=(*it).second;
8645           std::set<int> s2; s2.insert(prev);
8646           std::set<int> s3;
8647           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8648           if(s3.size()==1)
8649             {
8650               int val=*s3.begin();
8651               conn.push_back(start);
8652               prev=start;
8653               start=val;
8654             }
8655           else
8656             start=end;
8657         }
8658       conn.push_back(end);
8659       if(conn.size()>3)
8660         {
8661           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8662           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8663           cellIds->pushBackSilent(i);
8664         }
8665     }
8666 }
8667
8668 /*!
8669  * 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
8670  * 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
8671  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8672  * 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
8673  * 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.
8674  * 
8675  * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8676  */
8677 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8678 {
8679   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8680   if(sz>=4)
8681     {
8682       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8683       if(cm.getDimension()==2)
8684         {
8685           const int *node=nodalConnBg+1;
8686           int startNode=*node++;
8687           double refX=coords[2*startNode];
8688           for(;node!=nodalConnEnd;node++)
8689             {
8690               if(coords[2*(*node)]<refX)
8691                 {
8692                   startNode=*node;
8693                   refX=coords[2*startNode];
8694                 }
8695             }
8696           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8697           refX=1e300;
8698           double tmp1;
8699           double tmp2[2];
8700           double angle0=-M_PI/2;
8701           //
8702           int nextNode=-1;
8703           int prevNode=-1;
8704           double resRef;
8705           double angleNext;
8706           while(nextNode!=startNode)
8707             {
8708               nextNode=-1;
8709               resRef=1e300;
8710               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8711                 {
8712                   if(*node!=tmpOut.back() && *node!=prevNode)
8713                     {
8714                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8715                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8716                       double res;
8717                       if(angleM<=angle0)
8718                         res=angle0-angleM;
8719                       else
8720                         res=angle0-angleM+2.*M_PI;
8721                       if(res<resRef)
8722                         {
8723                           nextNode=*node;
8724                           resRef=res;
8725                           angleNext=angleM;
8726                         }
8727                     }
8728                 }
8729               if(nextNode!=startNode)
8730                 {
8731                   angle0=angleNext-M_PI;
8732                   if(angle0<-M_PI)
8733                     angle0+=2*M_PI;
8734                   prevNode=tmpOut.back();
8735                   tmpOut.push_back(nextNode);
8736                 }
8737             }
8738           std::vector<int> tmp3(2*(sz-1));
8739           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8740           std::copy(nodalConnBg+1,nodalConnEnd,it);
8741           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8742             {
8743               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8744               return false;
8745             }
8746           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8747             {
8748               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8749               return false;
8750             }
8751           else
8752             {
8753               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8754               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8755               return true;
8756             }
8757         }
8758       else
8759         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8760     }
8761   else
8762     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8763 }
8764
8765 /*!
8766  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8767  * 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.
8768  * 
8769  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8770  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8771  * \param [in,out] arr array in which the remove operation will be done.
8772  * \param [in,out] arrIndx array in the remove operation will modify
8773  * \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])
8774  * \return true if \b arr and \b arrIndx have been modified, false if not.
8775  */
8776 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8777 {
8778   if(!arrIndx || !arr)
8779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8780   if(offsetForRemoval<0)
8781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8782   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8783   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8784   int *arrIPtr=arrIndx->getPointer();
8785   *arrIPtr++=0;
8786   int previousArrI=0;
8787   const int *arrPtr=arr->getConstPointer();
8788   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8789   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8790     {
8791       if(*arrIPtr-previousArrI>offsetForRemoval)
8792         {
8793           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8794             {
8795               if(s.find(*work)==s.end())
8796                 arrOut.push_back(*work);
8797             }
8798         }
8799       previousArrI=*arrIPtr;
8800       *arrIPtr=(int)arrOut.size();
8801     }
8802   if(arr->getNumberOfTuples()==(int)arrOut.size())
8803     return false;
8804   arr->alloc((int)arrOut.size(),1);
8805   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8806   return true;
8807 }
8808
8809 /*!
8810  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8811  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8812  * The selection of extraction is done standardly in new2old format.
8813  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8814  *
8815  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8816  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8817  * \param [in] arrIn arr origin array from which the extraction will be done.
8818  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8819  * \param [out] arrOut the resulting array
8820  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8821  */
8822 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8823                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8824 {
8825   if(!arrIn || !arrIndxIn)
8826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8827   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8828   const int *arrInPtr=arrIn->getConstPointer();
8829   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8830   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8831   int maxSizeOfArr=arrIn->getNumberOfTuples();
8832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8834   arrIo->alloc((int)(sz+1),1);
8835   const int *idsIt=idsOfSelectBg;
8836   int *work=arrIo->getPointer();
8837   *work++=0;
8838   int lgth=0;
8839   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8840     {
8841       if(*idsIt>=0 && *idsIt<nbOfGrps)
8842         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8843       else
8844         {
8845           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8846           throw INTERP_KERNEL::Exception(oss.str().c_str());
8847         }
8848       if(lgth>=work[-1])
8849         *work=lgth;
8850       else
8851         {
8852           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8853           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8854           throw INTERP_KERNEL::Exception(oss.str().c_str());
8855         }
8856     }
8857   arro->alloc(lgth,1);
8858   work=arro->getPointer();
8859   idsIt=idsOfSelectBg;
8860   for(std::size_t i=0;i<sz;i++,idsIt++)
8861     {
8862       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8863         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8864       else
8865         {
8866           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8867           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8868           throw INTERP_KERNEL::Exception(oss.str().c_str());
8869         }
8870     }
8871   arrOut=arro.retn();
8872   arrIndexOut=arrIo.retn();
8873 }
8874
8875 /*!
8876  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8877  * 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
8878  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8879  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8880  *
8881  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8882  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8883  * \param [in] arrIn arr origin array from which the extraction will be done.
8884  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8885  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8886  * \param [in] srcArrIndex index array of \b srcArr
8887  * \param [out] arrOut the resulting array
8888  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8889  * 
8890  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8891  */
8892 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8893                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8894                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8895 {
8896   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8900   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8901   std::vector<bool> v(nbOfTuples,true);
8902   int offset=0;
8903   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8904   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8905   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8906     {
8907       if(*it>=0 && *it<nbOfTuples)
8908         {
8909           v[*it]=false;
8910           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8911         }
8912       else
8913         {
8914           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8915           throw INTERP_KERNEL::Exception(oss.str().c_str());
8916         }
8917     }
8918   srcArrIndexPtr=srcArrIndex->getConstPointer();
8919   arrIo->alloc(nbOfTuples+1,1);
8920   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8921   const int *arrInPtr=arrIn->getConstPointer();
8922   const int *srcArrPtr=srcArr->getConstPointer();
8923   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8924   int *arroPtr=arro->getPointer();
8925   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8926     {
8927       if(v[ii])
8928         {
8929           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8930           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8931         }
8932       else
8933         {
8934           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8935           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8936           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8937         }
8938     }
8939   arrOut=arro.retn();
8940   arrIndexOut=arrIo.retn();
8941 }
8942
8943 /*!
8944  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8945  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8946  *
8947  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8948  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8949  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8950  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8951  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8952  * \param [in] srcArrIndex index array of \b srcArr
8953  * 
8954  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8955  */
8956 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8957                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8958 {
8959   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8960     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8961   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8962   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8963   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8964   int *arrInOutPtr=arrInOut->getPointer();
8965   const int *srcArrPtr=srcArr->getConstPointer();
8966   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8967     {
8968       if(*it>=0 && *it<nbOfTuples)
8969         {
8970           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8971             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8972           else
8973             {
8974               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] !";
8975               throw INTERP_KERNEL::Exception(oss.str().c_str());
8976             }
8977         }
8978       else
8979         {
8980           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8981           throw INTERP_KERNEL::Exception(oss.str().c_str());
8982         }
8983     }
8984 }
8985
8986 /*!
8987  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8988  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8989  * 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]].
8990  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8991  * A negative value in \b arrIn means that it is ignored.
8992  * 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.
8993  * 
8994  * \param [in] arrIn arr origin array from which the extraction will be done.
8995  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8996  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8997  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8998  */
8999 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9000 {
9001   int seed=0,nbOfDepthPeelingPerformed=0;
9002   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9003 }
9004
9005 /*!
9006  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9007  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9008  * 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]].
9009  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9010  * A negative value in \b arrIn means that it is ignored.
9011  * 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.
9012  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9013  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9014  * \param [in] arrIn arr origin array from which the extraction will be done.
9015  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9016  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9017  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9018  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9019  * \sa MEDCouplingUMesh::partitionBySpreadZone
9020  */
9021 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9022 {
9023   nbOfDepthPeelingPerformed=0;
9024   if(!arrIndxIn)
9025     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9026   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9027   if(nbOfTuples<=0)
9028     {
9029       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9030       return ret;
9031     }
9032   //
9033   std::vector<bool> fetched(nbOfTuples,false);
9034   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9035 }
9036
9037 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)
9038 {
9039   nbOfDepthPeelingPerformed=0;
9040   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9041     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9042   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9043   std::vector<bool> fetched2(nbOfTuples,false);
9044   int i=0;
9045   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9046     {
9047       if(*seedElt>=0 && *seedElt<nbOfTuples)
9048         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9049       else
9050         { 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()); }
9051     }
9052   const int *arrInPtr=arrIn->getConstPointer();
9053   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9054   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9055   std::vector<int> idsToFetch1(seedBg,seedEnd);
9056   std::vector<int> idsToFetch2;
9057   std::vector<int> *idsToFetch=&idsToFetch1;
9058   std::vector<int> *idsToFetchOther=&idsToFetch2;
9059   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9060     {
9061       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9062         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9063           if(!fetched[*it2])
9064             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9065       std::swap(idsToFetch,idsToFetchOther);
9066       idsToFetchOther->clear();
9067       nbOfDepthPeelingPerformed++;
9068     }
9069   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9070   i=0;
9071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9072   int *retPtr=ret->getPointer();
9073   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9074     if(*it)
9075       *retPtr++=i;
9076   return ret.retn();
9077 }
9078
9079 /*!
9080  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9081  * 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
9082  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9083  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9084  *
9085  * \param [in] start begin of set of ids of the input extraction (included)
9086  * \param [in] end end of set of ids of the input extraction (excluded)
9087  * \param [in] step step of the set of ids in range mode.
9088  * \param [in] arrIn arr origin array from which the extraction will be done.
9089  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9090  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9091  * \param [in] srcArrIndex index array of \b srcArr
9092  * \param [out] arrOut the resulting array
9093  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9094  * 
9095  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9096  */
9097 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9098                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9099                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9100 {
9101   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9105   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9106   int offset=0;
9107   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9108   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9109   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9110   int it=start;
9111   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9112     {
9113       if(it>=0 && it<nbOfTuples)
9114         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9115       else
9116         {
9117           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9118           throw INTERP_KERNEL::Exception(oss.str().c_str());
9119         }
9120     }
9121   srcArrIndexPtr=srcArrIndex->getConstPointer();
9122   arrIo->alloc(nbOfTuples+1,1);
9123   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9124   const int *arrInPtr=arrIn->getConstPointer();
9125   const int *srcArrPtr=srcArr->getConstPointer();
9126   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9127   int *arroPtr=arro->getPointer();
9128   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9129     {
9130       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9131       if(pos<0)
9132         {
9133           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9134           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9135         }
9136       else
9137         {
9138           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9139           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9140         }
9141     }
9142   arrOut=arro.retn();
9143   arrIndexOut=arrIo.retn();
9144 }
9145
9146 /*!
9147  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9148  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9149  *
9150  * \param [in] start begin of set of ids of the input extraction (included)
9151  * \param [in] end end of set of ids of the input extraction (excluded)
9152  * \param [in] step step of the set of ids in range mode.
9153  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9154  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9155  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9156  * \param [in] srcArrIndex index array of \b srcArr
9157  * 
9158  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9159  */
9160 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9161                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9162 {
9163   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9165   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9166   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9167   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9168   int *arrInOutPtr=arrInOut->getPointer();
9169   const int *srcArrPtr=srcArr->getConstPointer();
9170   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9171   int it=start;
9172   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9173     {
9174       if(it>=0 && it<nbOfTuples)
9175         {
9176           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9177             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9178           else
9179             {
9180               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9181               throw INTERP_KERNEL::Exception(oss.str().c_str());
9182             }
9183         }
9184       else
9185         {
9186           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9187           throw INTERP_KERNEL::Exception(oss.str().c_str());
9188         }
9189     }
9190 }
9191
9192 /*!
9193  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9194  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9195  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9196  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9197  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9198  * 
9199  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9200  */
9201 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9202 {
9203   checkFullyDefined();
9204   int mdim=getMeshDimension();
9205   int spaceDim=getSpaceDimension();
9206   if(mdim!=spaceDim)
9207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9208   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9209   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9210   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9211   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9212   ret->setCoords(getCoords());
9213   ret->allocateCells((int)partition.size());
9214   //
9215   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9216     {
9217       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9218       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9219       switch(mdim)
9220         {
9221         case 2:
9222           cell=tmp->buildUnionOf2DMesh();
9223           break;
9224         case 3:
9225           cell=tmp->buildUnionOf3DMesh();
9226           break;
9227         default:
9228           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9229         }
9230       
9231       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9232     }
9233   //
9234   ret->finishInsertingCells();
9235   return ret.retn();
9236 }
9237
9238 /*!
9239  * This method partitions \b this into contiguous zone.
9240  * This method only needs a well defined connectivity. Coordinates are not considered here.
9241  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9242  */
9243 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9244 {
9245   //#if 0
9246   int nbOfCellsCur=getNumberOfCells();
9247   std::vector<DataArrayInt *> ret;
9248   if(nbOfCellsCur<=0)
9249     return ret;
9250   DataArrayInt *neigh=0,*neighI=0;
9251   computeNeighborsOfCells(neigh,neighI);
9252   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9253   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9254   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9255   int seed=0;
9256   while(seed<nbOfCellsCur)
9257     {
9258       int nbOfPeelPerformed=0;
9259       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9260       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9261     }
9262   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9263     ret.push_back((*it).retn());
9264   return ret;
9265   //#endif
9266 #if 0
9267   int nbOfCellsCur=getNumberOfCells();
9268   DataArrayInt *neigh=0,*neighI=0;
9269   computeNeighborsOfCells(neigh,neighI);
9270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9272   std::vector<DataArrayInt *> ret;
9273   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9274   while(nbOfCellsCur>0)
9275     {
9276       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9277       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9278       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9279       ret2.push_back(tmp2);  ret.push_back(tmp2);
9280       nbOfCellsCur=tmp3->getNumberOfTuples();
9281       if(nbOfCellsCur>0)
9282         {
9283           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9284           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9285           neighAuto=neigh;
9286           neighIAuto=neighI;
9287           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9288           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9289         }
9290     }
9291   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9292     (*it)->incrRef();
9293   return ret;
9294 #endif
9295 }
9296
9297 /*!
9298  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9299  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9300  *
9301  * \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.
9302  * \return a newly allocated DataArrayInt to be managed by the caller.
9303  * \throw In case of \a code has not the right format (typically of size 3*n)
9304  */
9305 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9306 {
9307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9308   std::size_t nb=code.size()/3;
9309   if(code.size()%3!=0)
9310     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9311   ret->alloc((int)nb,2);
9312   int *retPtr=ret->getPointer();
9313   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9314     {
9315       retPtr[0]=code[3*i+2];
9316       retPtr[1]=code[3*i+2]+code[3*i+1];
9317     }
9318   return ret.retn();
9319 }
9320
9321 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9322                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9323 {
9324   if(mesh)
9325     {
9326       mesh->incrRef();
9327       _nb_cell=mesh->getNumberOfCells();
9328     }
9329 }
9330
9331 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9332 {
9333   if(_mesh)
9334     _mesh->decrRef();
9335   if(_own_cell)
9336     delete _cell;
9337 }
9338
9339 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9340                                                                                                                                _own_cell(false),_cell_id(bg-1),
9341                                                                                                                                _nb_cell(end)
9342 {
9343   if(mesh)
9344     mesh->incrRef();
9345 }
9346
9347 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9348 {
9349   _cell_id++;
9350   if(_cell_id<_nb_cell)
9351     {
9352       _cell->next();
9353       return _cell;
9354     }
9355   else
9356     return 0;
9357 }
9358
9359 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9360 {
9361   if(_mesh)
9362     _mesh->incrRef();
9363 }
9364
9365 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9366 {
9367   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9368 }
9369
9370 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9371 {
9372   if(_mesh)
9373     _mesh->decrRef();
9374 }
9375
9376 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9377                                                                                                                                                                   _itc(itc),
9378                                                                                                                                                                   _bg(bg),_end(end)
9379 {
9380   if(_mesh)
9381     _mesh->incrRef();
9382 }
9383
9384 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9385 {
9386   if(_mesh)
9387     _mesh->decrRef();
9388 }
9389
9390 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9391 {
9392   return _type;
9393 }
9394
9395 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9396 {
9397   return _end-_bg;
9398 }
9399
9400 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9401 {
9402   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9403 }
9404
9405 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9406 {
9407   if(mesh)
9408     {
9409       mesh->incrRef();
9410       _nb_cell=mesh->getNumberOfCells();
9411     }
9412 }
9413
9414 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9415 {
9416   if(_mesh)
9417     _mesh->decrRef();
9418   delete _cell;
9419 }
9420
9421 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9422 {
9423   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9424   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9425   if(_cell_id<_nb_cell)
9426     {
9427       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9428       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9429       int startId=_cell_id;
9430       _cell_id+=nbOfElems;
9431       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9432     }
9433   else
9434     return 0;
9435 }
9436
9437 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9438 {
9439   if(mesh)
9440     {
9441       _conn=mesh->getNodalConnectivity()->getPointer();
9442       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9443     }
9444 }
9445
9446 void MEDCouplingUMeshCell::next()
9447 {
9448   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9449     {
9450       _conn+=_conn_lgth;
9451       _conn_indx++;
9452     }
9453   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9454 }
9455
9456 std::string MEDCouplingUMeshCell::repr() const
9457 {
9458   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9459     {
9460       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9461       oss << " : ";
9462       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9463       return oss.str();
9464     }
9465   else
9466     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9467 }
9468
9469 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9470 {
9471   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9472     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9473   else
9474     return INTERP_KERNEL::NORM_ERROR;
9475 }
9476
9477 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9478 {
9479   lgth=_conn_lgth;
9480   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9481     return _conn;
9482   else
9483     return 0;
9484 }