Salome HOME
41784fb2fbebfd2e81d0110352b4853e7e87ce7b
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 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 };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
128   ret.push_back(_nodal_connec);
129   ret.push_back(_nodal_connec_index);
130   return ret;
131 }
132
133 void MEDCouplingUMesh::updateTime() const
134 {
135   MEDCouplingPointSet::updateTime();
136   if(_nodal_connec)
137     {
138       updateTimeWith(*_nodal_connec);
139     }
140   if(_nodal_connec_index)
141     {
142       updateTimeWith(*_nodal_connec_index);
143     }
144 }
145
146 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
147 {
148 }
149
150 /*!
151  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
152  * then \a this mesh is most probably is writable, exchangeable and available for most
153  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
154  * this method to check that all is in order with \a this mesh.
155  *  \throw If the mesh dimension is not set.
156  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
157  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
158  *  \throw If the connectivity data array has more than one component.
159  *  \throw If the connectivity data array has a named component.
160  *  \throw If the connectivity index data array has more than one component.
161  *  \throw If the connectivity index data array has a named component.
162  */
163 void MEDCouplingUMesh::checkCoherency() const
164 {
165   if(_mesh_dim<-1)
166     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
167   if(_mesh_dim!=-1)
168     MEDCouplingPointSet::checkCoherency();
169   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
170     {
171       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
172         {
173           std::ostringstream message;
174           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
175           throw INTERP_KERNEL::Exception(message.str().c_str());
176         }
177     }
178   if(_nodal_connec)
179     {
180       if(_nodal_connec->getNumberOfComponents()!=1)
181         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
182       if(_nodal_connec->getInfoOnComponent(0)!="")
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
184     }
185   else
186     if(_mesh_dim!=-1)
187       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
188   if(_nodal_connec_index)
189     {
190       if(_nodal_connec_index->getNumberOfComponents()!=1)
191         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
192       if(_nodal_connec_index->getInfoOnComponent(0)!="")
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
194     }
195   else
196     if(_mesh_dim!=-1)
197       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
198 }
199
200 /*!
201  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
202  * then \a this mesh is most probably is writable, exchangeable and available for all
203  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
204  * method thoroughly checks the nodal connectivity.
205  *  \param [in] eps - a not used parameter.
206  *  \throw If the mesh dimension is not set.
207  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
208  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
209  *  \throw If the connectivity data array has more than one component.
210  *  \throw If the connectivity data array has a named component.
211  *  \throw If the connectivity index data array has more than one component.
212  *  \throw If the connectivity index data array has a named component.
213  *  \throw If number of nodes defining an element does not correspond to the type of element.
214  *  \throw If the nodal connectivity includes an invalid node id.
215  */
216 void MEDCouplingUMesh::checkCoherency1(double eps) const
217 {
218   checkCoherency();
219   if(_mesh_dim==-1)
220     return ;
221   int meshDim=getMeshDimension();
222   int nbOfNodes=getNumberOfNodes();
223   int nbOfCells=getNumberOfCells();
224   const int *ptr=_nodal_connec->getConstPointer();
225   const int *ptrI=_nodal_connec_index->getConstPointer();
226   for(int i=0;i<nbOfCells;i++)
227     {
228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
229       if((int)cm.getDimension()!=meshDim)
230         {
231           std::ostringstream oss;
232           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
233           throw INTERP_KERNEL::Exception(oss.str().c_str());
234         }
235       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
236       if(!cm.isDynamic())
237         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
238           {
239             std::ostringstream oss;
240             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
241             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
242             throw INTERP_KERNEL::Exception(oss.str().c_str());
243           }
244       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
245         {
246           int nodeId=*w;
247           if(nodeId>=0)
248             {
249               if(nodeId>=nbOfNodes)
250                 {
251                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
252                   throw INTERP_KERNEL::Exception(oss.str().c_str());
253                 }
254             }
255           else if(nodeId<-1)
256             {
257               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
258               throw INTERP_KERNEL::Exception(oss.str().c_str());
259             }
260           else
261             {
262               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268         }
269     }
270 }
271
272
273 /*!
274  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
275  * then \a this mesh is most probably is writable, exchangeable and available for all
276  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
277  *  \param [in] eps - a not used parameter.
278  *  \throw If the mesh dimension is not set.
279  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
280  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
281  *  \throw If the connectivity data array has more than one component.
282  *  \throw If the connectivity data array has a named component.
283  *  \throw If the connectivity index data array has more than one component.
284  *  \throw If the connectivity index data array has a named component.
285  *  \throw If number of nodes defining an element does not correspond to the type of element.
286  *  \throw If the nodal connectivity includes an invalid node id.
287  */
288 void MEDCouplingUMesh::checkCoherency2(double eps) const
289 {
290   checkCoherency1(eps);
291 }
292
293 /*!
294  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
295  * elements contained in the mesh. For more info on the mesh dimension see
296  * \ref MEDCouplingUMeshPage.
297  *  \param [in] meshDim - a new mesh dimension.
298  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
299  */
300 void MEDCouplingUMesh::setMeshDimension(int meshDim)
301 {
302   if(meshDim<-1 || meshDim>3)
303     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
304   _mesh_dim=meshDim;
305   declareAsNew();
306 }
307
308 /*!
309  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
310  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
311  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
312  *
313  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
314  *
315  *  \if ENABLE_EXAMPLES
316  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
317  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
318  *  \endif
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \if ENABLE_EXAMPLES
349  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
350  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
351  *  \endif
352  */
353 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
354 {
355   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
356   if(_nodal_connec_index==0)
357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
358   if((int)cm.getDimension()==_mesh_dim)
359     {
360       if(!cm.isDynamic())
361         if(size!=(int)cm.getNumberOfNodes())
362           {
363             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
364             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
365             throw INTERP_KERNEL::Exception(oss.str().c_str());
366           }
367       int idx=_nodal_connec_index->back();
368       int val=idx+size+1;
369       _nodal_connec_index->pushBackSilent(val);
370       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
371       _types.insert(type);
372     }
373   else
374     {
375       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
376       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
377       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
378       throw INTERP_KERNEL::Exception(oss.str().c_str());
379     }
380 }
381
382 /*!
383  * Compacts data arrays to release unused memory. This method is to be called after
384  * finishing cell insertion using \a this->insertNextCell().
385  * 
386  *  \if ENABLE_EXAMPLES
387  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
388  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
389  *  \endif
390  */
391 void MEDCouplingUMesh::finishInsertingCells()
392 {
393   _nodal_connec->pack();
394   _nodal_connec_index->pack();
395   _nodal_connec->declareAsNew();
396   _nodal_connec_index->declareAsNew();
397   updateTime();
398 }
399
400 /*!
401  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
402  * Useful for python users.
403  */
404 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
405 {
406   return new MEDCouplingUMeshCellIterator(this);
407 }
408
409 /*!
410  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
411  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
412  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
413  * Useful for python users.
414  */
415 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
416 {
417   if(!checkConsecutiveCellTypes())
418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
419   return new MEDCouplingUMeshCellByTypeEntry(this);
420 }
421
422 /*!
423  * Returns a set of all cell types available in \a this mesh.
424  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
425  * \warning this method does not throw any exception even if \a this is not defined.
426  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
427  */
428 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
429 {
430   return _types;
431 }
432
433 /*!
434  * This method returns the sorted list of geometric types in \a this.
435  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
436  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
437  *
438  * \throw if connectivity in \a this is not correctly defined.
439  *  
440  * \sa MEDCouplingMesh::getAllGeoTypes
441  */
442 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
443 {
444   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
445   checkConnectivityFullyDefined();
446   int nbOfCells(getNumberOfCells());
447   if(nbOfCells==0)
448     return ret;
449   if(getMeshLength()<1)
450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
451   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
452   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
453   for(int i=1;i<nbOfCells;i++,ci++)
454     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
455       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
456   return ret;
457 }
458
459 /*!
460  * This method is a method that compares \a this and \a other.
461  * This method compares \b all attributes, even names and component names.
462  */
463 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
464 {
465   if(!other)
466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
467   std::ostringstream oss; oss.precision(15);
468   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
469   if(!otherC)
470     {
471       reason="mesh given in input is not castable in MEDCouplingUMesh !";
472       return false;
473     }
474   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
475     return false;
476   if(_mesh_dim!=otherC->_mesh_dim)
477     {
478       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
479       reason=oss.str();
480       return false;
481     }
482   if(_types!=otherC->_types)
483     {
484       oss << "umesh geometric type mismatch :\nThis geometric types are :";
485       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
486         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487       oss << "\nOther geometric types are :";
488       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
489         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
490       reason=oss.str();
491       return false;
492     }
493   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
494     if(_nodal_connec==0 || otherC->_nodal_connec==0)
495       {
496         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
497         return false;
498       }
499   if(_nodal_connec!=otherC->_nodal_connec)
500     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
501       {
502         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
503         return false;
504       }
505   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
506     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
507       {
508         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
509         return false;
510       }
511   if(_nodal_connec_index!=otherC->_nodal_connec_index)
512     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
513       {
514         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
515         return false;
516       }
517   return true;
518 }
519
520 /*!
521  * Checks if data arrays of this mesh (node coordinates, nodal
522  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
523  * not considered.
524  *  \param [in] other - the mesh to compare with.
525  *  \param [in] prec - precision value used to compare node coordinates.
526  *  \return bool - \a true if the two meshes are same.
527  */
528 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
529 {
530   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
531   if(!otherC)
532     return false;
533   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
534     return false;
535   if(_mesh_dim!=otherC->_mesh_dim)
536     return false;
537   if(_types!=otherC->_types)
538     return false;
539   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
540     if(_nodal_connec==0 || otherC->_nodal_connec==0)
541       return false;
542   if(_nodal_connec!=otherC->_nodal_connec)
543     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
544       return false;
545   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
546     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
547       return false;
548   if(_nodal_connec_index!=otherC->_nodal_connec_index)
549     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
550       return false;
551   return true;
552 }
553
554 /*!
555  * Checks if \a this and \a other meshes are geometrically equivalent with high
556  * probability, else an exception is thrown. The meshes are considered equivalent if
557  * (1) meshes contain the same number of nodes and the same number of elements of the
558  * same types (2) three cells of the two meshes (first, last and middle) are based
559  * on coincident nodes (with a specified precision).
560  *  \param [in] other - the mesh to compare with.
561  *  \param [in] prec - the precision used to compare nodes of the two meshes.
562  *  \throw If the two meshes do not match.
563  */
564 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
565 {
566   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
567   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
568   if(!otherC)
569     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
570 }
571
572 /*!
573  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
574  * cells each node belongs to.
575  * \warning For speed reasons, this method does not check if node ids in the nodal
576  *          connectivity correspond to the size of node coordinates array.
577  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
578  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
579  *        dividing cell ids in \a revNodal into groups each referring to one
580  *        node. Its every element (except the last one) is an index pointing to the
581  *         first id of a group of cells. For example cells sharing the node #1 are 
582  *        described by following range of indices: 
583  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
584  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
585  *        Number of cells sharing the *i*-th node is
586  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
587  * \throw If the coordinates array is not set.
588  * \throw If the nodal connectivity of cells is not defined.
589  * 
590  * \if ENABLE_EXAMPLES
591  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
592  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
593  * \endif
594  */
595 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
596 {
597   checkFullyDefined();
598   int nbOfNodes=getNumberOfNodes();
599   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
600   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
601   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
602   const int *conn=_nodal_connec->getConstPointer();
603   const int *connIndex=_nodal_connec_index->getConstPointer();
604   int nbOfCells=getNumberOfCells();
605   int nbOfEltsInRevNodal=0;
606   for(int eltId=0;eltId<nbOfCells;eltId++)
607     {
608       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
609       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
610       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
611         if(*iter>=0)//for polyhedrons
612           {
613             nbOfEltsInRevNodal++;
614             revNodalIndxPtr[(*iter)+1]++;
615           }
616     }
617   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
618   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
619   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
620   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
621   for(int eltId=0;eltId<nbOfCells;eltId++)
622     {
623       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
624       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
625       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
626         if(*iter>=0)//for polyhedrons
627           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
628     }
629 }
630
631 /// @cond INTERNAL
632
633 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
634 {
635   return id;
636 }
637
638 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
639 {
640   if(!compute)
641     return id+1;
642   else
643     {
644       if(cm.getOrientationStatus(nb,conn1,conn2))
645         return id+1;
646       else
647         return -(id+1);
648     }
649 }
650
651 class MinusOneSonsGenerator
652 {
653 public:
654   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
655   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
656   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
657   static const int DELTA=1;
658 private:
659   const INTERP_KERNEL::CellModel& _cm;
660 };
661
662 class MinusOneSonsGeneratorBiQuadratic
663 {
664 public:
665   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
666   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
667   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
668   static const int DELTA=1;
669 private:
670   const INTERP_KERNEL::CellModel& _cm;
671 };
672
673 class MinusTwoSonsGenerator
674 {
675 public:
676   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
677   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
678   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
679   static const int DELTA=2;
680 private:
681   const INTERP_KERNEL::CellModel& _cm;
682 };
683
684 /// @endcond
685
686 /*!
687  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
688  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
689  * describing correspondence between cells of \a this and the result meshes are
690  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
691  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
692  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
693  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
694  * \warning For speed reasons, this method does not check if node ids in the nodal
695  *          connectivity correspond to the size of node coordinates array.
696  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
697  *          to write this mesh to the MED file, its cells must be sorted using
698  *          sortCellsInMEDFileFrmt().
699  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
700  *         each cell of \a this mesh.
701  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
702  *        dividing cell ids in \a desc into groups each referring to one
703  *        cell of \a this mesh. Its every element (except the last one) is an index
704  *        pointing to the first id of a group of cells. For example cells of the
705  *        result mesh bounding the cell #1 of \a this mesh are described by following
706  *        range of indices:
707  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
708  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
709  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
710  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
711  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
712  *         by each cell of the result mesh.
713  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
714  *        in the result mesh,
715  *        dividing cell ids in \a revDesc into groups each referring to one
716  *        cell of the result mesh the same way as \a descIndx divides \a desc.
717  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
718  *        delete this mesh using decrRef() as it is no more needed.
719  *  \throw If the coordinates array is not set.
720  *  \throw If the nodal connectivity of cells is node defined.
721  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
722  *         revDescIndx == NULL.
723  * 
724  *  \if ENABLE_EXAMPLES
725  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
726  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
727  *  \endif
728  * \sa buildDescendingConnectivity2()
729  */
730 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
731 {
732   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
733 }
734
735 /*!
736  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
737  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
738  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
739  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
740  * \sa MEDCouplingUMesh::buildDescendingConnectivity
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
743 {
744   checkFullyDefined();
745   if(getMeshDimension()!=3)
746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
747   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
748 }
749
750 /*!
751  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
752  * this->getMeshDimension(), that bound cells of \a this mesh. In
753  * addition arrays describing correspondence between cells of \a this and the result
754  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
755  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
756  *  mesh. This method differs from buildDescendingConnectivity() in that apart
757  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
758  * result meshes. So a positive id means that order of nodes in corresponding cells
759  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
760  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
761  * i.e. cell ids are one-based.
762  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
763  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
764  * \warning For speed reasons, this method does not check if node ids in the nodal
765  *          connectivity correspond to the size of node coordinates array.
766  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
767  *          to write this mesh to the MED file, its cells must be sorted using
768  *          sortCellsInMEDFileFrmt().
769  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
770  *         each cell of \a this mesh.
771  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
772  *        dividing cell ids in \a desc into groups each referring to one
773  *        cell of \a this mesh. Its every element (except the last one) is an index
774  *        pointing to the first id of a group of cells. For example cells of the
775  *        result mesh bounding the cell #1 of \a this mesh are described by following
776  *        range of indices:
777  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
778  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
779  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
780  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
781  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
782  *         by each cell of the result mesh.
783  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
784  *        in the result mesh,
785  *        dividing cell ids in \a revDesc into groups each referring to one
786  *        cell of the result mesh the same way as \a descIndx divides \a desc.
787  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
788  *        shares the node coordinates array with \a this mesh. The caller is to
789  *        delete this mesh using decrRef() as it is no more needed.
790  *  \throw If the coordinates array is not set.
791  *  \throw If the nodal connectivity of cells is node defined.
792  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
793  *         revDescIndx == NULL.
794  * 
795  *  \if ENABLE_EXAMPLES
796  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
797  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
798  *  \endif
799  * \sa buildDescendingConnectivity()
800  */
801 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
802 {
803   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
804 }
805
806 /*!
807  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
808  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
809  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
810  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
811  *
812  * \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
813  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
814  * \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.
815  */
816 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
817 {
818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
823   meshDM1=0;
824   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
825 }
826
827 /*!
828  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
829  * 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,
830  * excluding a set of meshdim-1 cells in input descending connectivity.
831  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
832  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
833  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
834  *
835  * \param [in] desc descending connectivity array.
836  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
837  * \param [in] revDesc reverse descending connectivity array.
838  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
839  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
840  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
841  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
842  */
843 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
844                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
845 {
846   if(!desc || !descIndx || !revDesc || !revDescIndx)
847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
848   const int *descPtr=desc->getConstPointer();
849   const int *descIPtr=descIndx->getConstPointer();
850   const int *revDescPtr=revDesc->getConstPointer();
851   const int *revDescIPtr=revDescIndx->getConstPointer();
852   //
853   int nbCells=descIndx->getNumberOfTuples()-1;
854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
856   int *out1Ptr=out1->getPointer();
857   *out1Ptr++=0;
858   out0->reserve(desc->getNumberOfTuples());
859   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
860     {
861       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
862         {
863           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
864           s.erase(i);
865           out0->insertAtTheEnd(s.begin(),s.end());
866         }
867       *out1Ptr=out0->getNumberOfTuples();
868     }
869   neighbors=out0.retn();
870   neighborsIndx=out1.retn();
871 }
872
873 /*!
874  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
875  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
876  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
877  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
878  *
879  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
880  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
881  * \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.
882  */
883 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
884 {
885   checkFullyDefined();
886   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
888   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
889   switch(mdim)
890   {
891     case 3:
892       {
893         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
894         break;
895       }
896     case 2:
897       {
898         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
899         break;
900       }
901     case 1:
902       {
903         mesh1D=const_cast<MEDCouplingUMesh *>(this);
904         mesh1D->incrRef();
905         break;
906       }
907     default:
908       {
909         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
910       }
911   }
912   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
913   mesh1D->getReverseNodalConnectivity(desc,descIndx);
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
915   ret0->alloc(desc->getNumberOfTuples(),1);
916   int *r0Pt(ret0->getPointer());
917   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
918   for(int i=0;i<nbNodes;i++,rni++)
919     {
920       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
921         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
922     }
923   neighbors=ret0.retn();
924   neighborsIdx=descIndx.retn();
925 }
926
927 /// @cond INTERNAL
928
929 /*!
930  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
931  * For speed reasons no check of this will be done.
932  */
933 template<class SonsGenerator>
934 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
935 {
936   if(!desc || !descIndx || !revDesc || !revDescIndx)
937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
938   checkConnectivityFullyDefined();
939   int nbOfCells=getNumberOfCells();
940   int nbOfNodes=getNumberOfNodes();
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
942   int *revNodalIndxPtr=revNodalIndx->getPointer();
943   const int *conn=_nodal_connec->getConstPointer();
944   const int *connIndex=_nodal_connec_index->getConstPointer();
945   std::string name="Mesh constituent of "; name+=getName();
946   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
947   ret->setCoords(getCoords());
948   ret->allocateCells(2*nbOfCells);
949   descIndx->alloc(nbOfCells+1,1);
950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
951   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
952   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
953     {
954       int pos=connIndex[eltId];
955       int posP1=connIndex[eltId+1];
956       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
957       SonsGenerator sg(cm);
958       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
959       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
960       for(unsigned i=0;i<nbOfSons;i++)
961         {
962           INTERP_KERNEL::NormalizedCellType cmsId;
963           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
964           for(unsigned k=0;k<nbOfNodesSon;k++)
965             if(tmp[k]>=0)
966               revNodalIndxPtr[tmp[k]+1]++;
967           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
968           revDesc2->pushBackSilent(eltId);
969         }
970       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
971     }
972   int nbOfCellsM1=ret->getNumberOfCells();
973   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
975   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
976   int *revNodalPtr=revNodal->getPointer();
977   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
978   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
979   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
980     {
981       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
982       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
983       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
984         if(*iter>=0)//for polyhedrons
985           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
986     }
987   //
988   DataArrayInt *commonCells=0,*commonCellsI=0;
989   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
991   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
992   int newNbOfCellsM1=-1;
993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
994                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
995   std::vector<bool> isImpacted(nbOfCellsM1,false);
996   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
997     for(int work2=work[0];work2!=work[1];work2++)
998       isImpacted[commonCellsPtr[work2]]=true;
999   const int *o2nM1Ptr=o2nM1->getConstPointer();
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1001   const int *n2oM1Ptr=n2oM1->getConstPointer();
1002   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1003   ret2->copyTinyInfoFrom(this);
1004   desc->alloc(descIndx->back(),1);
1005   int *descPtr=desc->getPointer();
1006   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1007   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1008     {
1009       if(!isImpacted[i])
1010         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1011       else
1012         {
1013           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1014             {
1015               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1016               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1017             }
1018           else
1019             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1020         }
1021     }
1022   revDesc->reserve(newNbOfCellsM1);
1023   revDescIndx->alloc(newNbOfCellsM1+1,1);
1024   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1025   const int *revDesc2Ptr=revDesc2->getConstPointer();
1026   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1027     {
1028       int oldCellIdM1=n2oM1Ptr[i];
1029       if(!isImpacted[oldCellIdM1])
1030         {
1031           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1032           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1033         }
1034       else
1035         {
1036           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1037             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1038           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1039           commonCellsIPtr++;
1040         }
1041     }
1042   //
1043   return ret2.retn();
1044 }
1045
1046 struct MEDCouplingAccVisit
1047 {
1048   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1049   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1050   int _new_nb_of_nodes;
1051 };
1052
1053 /// @endcond
1054
1055 /*!
1056  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1057  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1058  * array of cell ids. Pay attention that after conversion all algorithms work slower
1059  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1060  * conversion due presence of invalid ids in the array of cells to convert, as a
1061  * result \a this mesh contains some already converted elements. In this case the 2D
1062  * mesh remains valid but 3D mesh becomes \b inconsistent!
1063  *  \warning This method can significantly modify the order of geometric types in \a this,
1064  *          hence, to write this mesh to the MED file, its cells must be sorted using
1065  *          sortCellsInMEDFileFrmt().
1066  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1067  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1068  *         cellIdsToConvertBg.
1069  *  \throw If the coordinates array is not set.
1070  *  \throw If the nodal connectivity of cells is node defined.
1071  *  \throw If dimension of \a this mesh is not either 2 or 3.
1072  *
1073  *  \if ENABLE_EXAMPLES
1074  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1075  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1076  *  \endif
1077  */
1078 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1079 {
1080   checkFullyDefined();
1081   int dim=getMeshDimension();
1082   if(dim<2 || dim>3)
1083     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1084   int nbOfCells(getNumberOfCells());
1085   if(dim==2)
1086     {
1087       const int *connIndex=_nodal_connec_index->getConstPointer();
1088       int *conn=_nodal_connec->getPointer();
1089       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1090         {
1091           if(*iter>=0 && *iter<nbOfCells)
1092             {
1093               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1094               if(!cm.isQuadratic())
1095                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1096               else
1097                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1098             }
1099           else
1100             {
1101               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1102               oss << " in range [0," << nbOfCells << ") !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105         }
1106     }
1107   else
1108     {
1109       int *connIndex(_nodal_connec_index->getPointer());
1110       const int *connOld(_nodal_connec->getConstPointer());
1111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1112       std::vector<bool> toBeDone(nbOfCells,false);
1113       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1114         {
1115           if(*iter>=0 && *iter<nbOfCells)
1116             toBeDone[*iter]=true;
1117           else
1118             {
1119               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1120               oss << " in range [0," << nbOfCells << ") !";
1121               throw INTERP_KERNEL::Exception(oss.str().c_str());
1122             }
1123         }
1124       for(int cellId=0;cellId<nbOfCells;cellId++)
1125         {
1126           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1127           int lgthOld(posP1-pos-1);
1128           if(toBeDone[cellId])
1129             {
1130               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1131               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1132               int *tmp(new int[nbOfFaces*lgthOld+1]);
1133               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1134               for(unsigned j=0;j<nbOfFaces;j++)
1135                 {
1136                   INTERP_KERNEL::NormalizedCellType type;
1137                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1138                   work+=offset;
1139                   *work++=-1;
1140                 }
1141               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1142               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1143               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1144               delete [] tmp;
1145             }
1146           else
1147             {
1148               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1149               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1150             }
1151         }
1152       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1153     }
1154   computeTypes();
1155 }
1156
1157 /*!
1158  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1159  * polyhedrons (if \a this is a 3D mesh).
1160  *  \warning As this method is purely for user-friendliness and no optimization is
1161  *          done to avoid construction of a useless vector, this method can be costly
1162  *          in memory.
1163  *  \throw If the coordinates array is not set.
1164  *  \throw If the nodal connectivity of cells is node defined.
1165  *  \throw If dimension of \a this mesh is not either 2 or 3.
1166  */
1167 void MEDCouplingUMesh::convertAllToPoly()
1168 {
1169   int nbOfCells=getNumberOfCells();
1170   std::vector<int> cellIds(nbOfCells);
1171   for(int i=0;i<nbOfCells;i++)
1172     cellIds[i]=i;
1173   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1174 }
1175
1176 /*!
1177  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1178  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1179  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1180  * base facet of the volume and the second half of nodes describes an opposite facet
1181  * having the same number of nodes as the base one. This method converts such
1182  * connectivity to a valid polyhedral format where connectivity of each facet is
1183  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1184  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1185  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1186  * a correct orientation of the first facet of a polyhedron, else orientation of a
1187  * corrected cell is reverse.<br>
1188  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1189  * it releases the user from boring description of polyhedra connectivity in the valid
1190  * format.
1191  *  \throw If \a this->getMeshDimension() != 3.
1192  *  \throw If \a this->getSpaceDimension() != 3.
1193  *  \throw If the nodal connectivity of cells is not defined.
1194  *  \throw If the coordinates array is not set.
1195  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1196  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1197  *
1198  *  \if ENABLE_EXAMPLES
1199  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1200  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1201  *  \endif
1202  */
1203 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1204 {
1205   checkFullyDefined();
1206   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1208   int nbOfCells=getNumberOfCells();
1209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1210   newCi->alloc(nbOfCells+1,1);
1211   int *newci=newCi->getPointer();
1212   const int *ci=_nodal_connec_index->getConstPointer();
1213   const int *c=_nodal_connec->getConstPointer();
1214   newci[0]=0;
1215   for(int i=0;i<nbOfCells;i++)
1216     {
1217       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1218       if(type==INTERP_KERNEL::NORM_POLYHED)
1219         {
1220           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1221             {
1222               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1223               throw INTERP_KERNEL::Exception(oss.str().c_str());
1224             }
1225           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1226           if(n2%2!=0)
1227             {
1228               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 !";
1229               throw INTERP_KERNEL::Exception(oss.str().c_str());
1230             }
1231           int n1=(int)(n2/2);
1232           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)
1233         }
1234       else
1235         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1236     }
1237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1238   newC->alloc(newci[nbOfCells],1);
1239   int *newc=newC->getPointer();
1240   for(int i=0;i<nbOfCells;i++)
1241     {
1242       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243       if(type==INTERP_KERNEL::NORM_POLYHED)
1244         {
1245           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1246           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1247           *newc++=-1;
1248           for(std::size_t j=0;j<n1;j++)
1249             {
1250               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1251               newc[n1+5*j]=-1;
1252               newc[n1+5*j+1]=c[ci[i]+1+j];
1253               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1254               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1255               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1256             }
1257           newc+=n1*6;
1258         }
1259       else
1260         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1261     }
1262   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1263   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1264 }
1265
1266
1267 /*!
1268  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1269  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1270  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1271  *          to write this mesh to the MED file, its cells must be sorted using
1272  *          sortCellsInMEDFileFrmt().
1273  * \return \c true if at least one cell has been converted, \c false else. In the
1274  *         last case the nodal connectivity remains unchanged.
1275  * \throw If the coordinates array is not set.
1276  * \throw If the nodal connectivity of cells is not defined.
1277  * \throw If \a this->getMeshDimension() < 0.
1278  */
1279 bool MEDCouplingUMesh::unPolyze()
1280 {
1281   checkFullyDefined();
1282   int mdim=getMeshDimension();
1283   if(mdim<0)
1284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1285   if(mdim<=1)
1286     return false;
1287   int nbOfCells=getNumberOfCells();
1288   if(nbOfCells<1)
1289     return false;
1290   int initMeshLgth=getMeshLength();
1291   int *conn=_nodal_connec->getPointer();
1292   int *index=_nodal_connec_index->getPointer();
1293   int posOfCurCell=0;
1294   int newPos=0;
1295   int lgthOfCurCell;
1296   bool ret=false;
1297   for(int i=0;i<nbOfCells;i++)
1298     {
1299       lgthOfCurCell=index[i+1]-posOfCurCell;
1300       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1301       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1302       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1303       int newLgth;
1304       if(cm.isDynamic())
1305         {
1306           switch(cm.getDimension())
1307           {
1308             case 2:
1309               {
1310                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1311                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1312                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1313                 break;
1314               }
1315             case 3:
1316               {
1317                 int nbOfFaces,lgthOfPolyhConn;
1318                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 1:
1323               {
1324                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1325                 break;
1326               }
1327           }
1328           ret=ret || (newType!=type);
1329           conn[newPos]=newType;
1330           newPos+=newLgth+1;
1331           posOfCurCell=index[i+1];
1332           index[i+1]=newPos;
1333         }
1334       else
1335         {
1336           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1337           newPos+=lgthOfCurCell;
1338           posOfCurCell+=lgthOfCurCell;
1339           index[i+1]=newPos;
1340         }
1341     }
1342   if(newPos!=initMeshLgth)
1343     _nodal_connec->reAlloc(newPos);
1344   if(ret)
1345     computeTypes();
1346   return ret;
1347 }
1348
1349 /*!
1350  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1351  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1352  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1353  *
1354  * \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 
1355  *             precision.
1356  */
1357 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1358 {
1359   checkFullyDefined();
1360   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1363   coords->recenterForMaxPrecision(eps);
1364   //
1365   int nbOfCells=getNumberOfCells();
1366   const int *conn=_nodal_connec->getConstPointer();
1367   const int *index=_nodal_connec_index->getConstPointer();
1368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1369   connINew->alloc(nbOfCells+1,1);
1370   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1372   bool changed=false;
1373   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1374     {
1375       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1376         {
1377           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1378           changed=true;
1379         }
1380       else
1381         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1382       *connINewPtr=connNew->getNumberOfTuples();
1383     }
1384   if(changed)
1385     setConnectivity(connNew,connINew,false);
1386 }
1387
1388 /*!
1389  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1390  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1391  * the format of returned DataArrayInt instance.
1392  * 
1393  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1394  * \sa MEDCouplingUMesh::getNodeIdsInUse
1395  */
1396 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1397 {
1398   checkConnectivityFullyDefined();
1399   int nbOfCells=getNumberOfCells();
1400   const int *connIndex=_nodal_connec_index->getConstPointer();
1401   const int *conn=_nodal_connec->getConstPointer();
1402   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1403   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1404   std::vector<bool> retS(maxElt,false);
1405   for(int i=0;i<nbOfCells;i++)
1406     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1407       if(conn[j]>=0)
1408         retS[conn[j]]=true;
1409   int sz=0;
1410   for(int i=0;i<maxElt;i++)
1411     if(retS[i])
1412       sz++;
1413   DataArrayInt *ret=DataArrayInt::New();
1414   ret->alloc(sz,1);
1415   int *retPtr=ret->getPointer();
1416   for(int i=0;i<maxElt;i++)
1417     if(retS[i])
1418       *retPtr++=i;
1419   return ret;
1420 }
1421
1422 /*!
1423  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1424  * \sa MEDCouplingUMesh::getNodeIdsInUse
1425  */
1426 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1427 {
1428   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1429   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1430   for(int i=0;i<nbOfCells;i++)
1431     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1432       if(conn[j]>=0)
1433         {
1434           if(conn[j]<nbOfNodes)
1435             nodeIdsInUse[conn[j]]=true;
1436           else
1437             {
1438               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1439               throw INTERP_KERNEL::Exception(oss.str().c_str());
1440             }
1441         }
1442 }
1443
1444 /*!
1445  * Finds nodes not used in any cell and returns an array giving a new id to every node
1446  * by excluding the unused nodes, for which the array holds -1. The result array is
1447  * a mapping in "Old to New" mode. 
1448  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1449  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1450  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1451  *          if the node is unused or a new id else. The caller is to delete this
1452  *          array using decrRef() as it is no more needed.  
1453  *  \throw If the coordinates array is not set.
1454  *  \throw If the nodal connectivity of cells is not defined.
1455  *  \throw If the nodal connectivity includes an invalid id.
1456  *
1457  *  \if ENABLE_EXAMPLES
1458  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1459  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1460  *  \endif
1461  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1462  */
1463 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1464 {
1465   nbrOfNodesInUse=-1;
1466   int nbOfNodes(getNumberOfNodes());
1467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1468   ret->alloc(nbOfNodes,1);
1469   int *traducer=ret->getPointer();
1470   std::fill(traducer,traducer+nbOfNodes,-1);
1471   int nbOfCells=getNumberOfCells();
1472   const int *connIndex=_nodal_connec_index->getConstPointer();
1473   const int *conn=_nodal_connec->getConstPointer();
1474   for(int i=0;i<nbOfCells;i++)
1475     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1476       if(conn[j]>=0)
1477         {
1478           if(conn[j]<nbOfNodes)
1479             traducer[conn[j]]=1;
1480           else
1481             {
1482               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1483               throw INTERP_KERNEL::Exception(oss.str().c_str());
1484             }
1485         }
1486   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1487   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1488   return ret.retn();
1489 }
1490
1491 /*!
1492  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1493  * For each cell in \b this the number of nodes constituting cell is computed.
1494  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1495  * So for pohyhedrons some nodes can be counted several times in the returned result.
1496  * 
1497  * \return a newly allocated array
1498  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1499  */
1500 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1501 {
1502   checkConnectivityFullyDefined();
1503   int nbOfCells=getNumberOfCells();
1504   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1505   ret->alloc(nbOfCells,1);
1506   int *retPtr=ret->getPointer();
1507   const int *conn=getNodalConnectivity()->getConstPointer();
1508   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1509   for(int i=0;i<nbOfCells;i++,retPtr++)
1510     {
1511       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1512         *retPtr=connI[i+1]-connI[i]-1;
1513       else
1514         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1515     }
1516   return ret.retn();
1517 }
1518
1519 /*!
1520  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1521  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1522  *
1523  * \return DataArrayInt * - new object to be deallocated by the caller.
1524  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1525  */
1526 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1527 {
1528   checkConnectivityFullyDefined();
1529   int nbOfCells=getNumberOfCells();
1530   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1531   ret->alloc(nbOfCells,1);
1532   int *retPtr=ret->getPointer();
1533   const int *conn=getNodalConnectivity()->getConstPointer();
1534   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1535   for(int i=0;i<nbOfCells;i++,retPtr++)
1536     {
1537       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1538       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539         *retPtr=(int)s.size();
1540       else
1541         {
1542           s.erase(-1);
1543           *retPtr=(int)s.size();
1544         }
1545     }
1546   return ret.retn();
1547 }
1548
1549 /*!
1550  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1551  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1552  * 
1553  * \return a newly allocated array
1554  */
1555 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1556 {
1557   checkConnectivityFullyDefined();
1558   int nbOfCells=getNumberOfCells();
1559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1560   ret->alloc(nbOfCells,1);
1561   int *retPtr=ret->getPointer();
1562   const int *conn=getNodalConnectivity()->getConstPointer();
1563   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1564   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1565     {
1566       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1567       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1568     }
1569   return ret.retn();
1570 }
1571
1572 /*!
1573  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1574  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1575  * array mean that the corresponding old node is no more used. 
1576  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1577  *           this->getNumberOfNodes() before call of this method. The caller is to
1578  *           delete this array using decrRef() as it is no more needed. 
1579  *  \throw If the coordinates array is not set.
1580  *  \throw If the nodal connectivity of cells is not defined.
1581  *  \throw If the nodal connectivity includes an invalid id.
1582  *
1583  *  \if ENABLE_EXAMPLES
1584  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1585  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1586  *  \endif
1587  */
1588 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1589 {
1590   return MEDCouplingPointSet::zipCoordsTraducer();
1591 }
1592
1593 /*!
1594  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1595  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1596  */
1597 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1598 {
1599   switch(compType)
1600   {
1601     case 0:
1602       return AreCellsEqual0(conn,connI,cell1,cell2);
1603     case 1:
1604       return AreCellsEqual1(conn,connI,cell1,cell2);
1605     case 2:
1606       return AreCellsEqual2(conn,connI,cell1,cell2);
1607     case 3:
1608       return AreCellsEqual3(conn,connI,cell1,cell2);
1609     case 7:
1610       return AreCellsEqual7(conn,connI,cell1,cell2);
1611   }
1612   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1613 }
1614
1615 /*!
1616  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1617  */
1618 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1619 {
1620   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1621     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1622   return 0;
1623 }
1624
1625 /*!
1626  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1627  */
1628 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   int sz=connI[cell1+1]-connI[cell1];
1631   if(sz==connI[cell2+1]-connI[cell2])
1632     {
1633       if(conn[connI[cell1]]==conn[connI[cell2]])
1634         {
1635           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1636           unsigned dim=cm.getDimension();
1637           if(dim!=3)
1638             {
1639               if(dim!=1)
1640                 {
1641                   int sz1=2*(sz-1);
1642                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1643                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1644                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1645                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1646                   return work!=tmp+sz1?1:0;
1647                 }
1648               else
1649                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1650             }
1651           else
1652             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1653         }
1654     }
1655   return 0;
1656 }
1657
1658 /*!
1659  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1660  */
1661 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1662 {
1663   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1664     {
1665       if(conn[connI[cell1]]==conn[connI[cell2]])
1666         {
1667           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1668           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1669           return s1==s2?1:0;
1670         }
1671     }
1672   return 0;
1673 }
1674
1675 /*!
1676  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1677  */
1678 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1679 {
1680   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1681     {
1682       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1683       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1684       return s1==s2?1:0;
1685     }
1686   return 0;
1687 }
1688
1689 /*!
1690  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1691  */
1692 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1693 {
1694   int sz=connI[cell1+1]-connI[cell1];
1695   if(sz==connI[cell2+1]-connI[cell2])
1696     {
1697       if(conn[connI[cell1]]==conn[connI[cell2]])
1698         {
1699           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1700           unsigned dim=cm.getDimension();
1701           if(dim!=3)
1702             {
1703               if(dim!=1)
1704                 {
1705                   int sz1=2*(sz-1);
1706                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1707                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1708                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1709                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1710                   if(work!=tmp+sz1)
1711                     return 1;
1712                   else
1713                     {
1714                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1715                       std::reverse_iterator<int *> it2((int *)tmp);
1716                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1717                         return 2;
1718                       else
1719                         return 0;
1720                     }
1721
1722                   return work!=tmp+sz1?1:0;
1723                 }
1724               else
1725                 {//case of SEG2 and SEG3
1726                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1727                     return 1;
1728                   if(!cm.isQuadratic())
1729                     {
1730                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1731                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1732                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1733                         return 2;
1734                       return 0;
1735                     }
1736                   else
1737                     {
1738                       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])
1739                         return 2;
1740                       return 0;
1741                     }
1742                 }
1743             }
1744           else
1745             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1746         }
1747     }
1748   return 0;
1749 }
1750
1751 /*!
1752  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1753  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1754  * and result remains unchanged.
1755  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1756  * If in 'candidates' pool -1 value is considered as an empty value.
1757  * WARNING this method returns only ONE set of result !
1758  */
1759 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1760 {
1761   if(candidates.size()<1)
1762     return false;
1763   bool ret=false;
1764   std::vector<int>::const_iterator iter=candidates.begin();
1765   int start=(*iter++);
1766   for(;iter!=candidates.end();iter++)
1767     {
1768       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1769       if(status!=0)
1770         {
1771           if(!ret)
1772             {
1773               result->pushBackSilent(start);
1774               ret=true;
1775             }
1776           if(status==1)
1777             result->pushBackSilent(*iter);
1778           else
1779             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1780         }
1781     }
1782   return ret;
1783 }
1784
1785 /*!
1786  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1787  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1788  *
1789  * \param [in] compType input specifying the technique used to compare cells each other.
1790  *   - 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.
1791  *   - 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)
1792  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1793  *   - 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
1794  * can be used for users not sensitive to orientation of cell
1795  * \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.
1796  * \param [out] commonCells
1797  * \param [out] commonCellsI
1798  * \return the correspondance array old to new in a newly allocated array.
1799  * 
1800  */
1801 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1802 {
1803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1804   getReverseNodalConnectivity(revNodal,revNodalI);
1805   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1806 }
1807
1808 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1809                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1810 {
1811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1812   int nbOfCells=nodalI->getNumberOfTuples()-1;
1813   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1814   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1815   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1816   std::vector<bool> isFetched(nbOfCells,false);
1817   if(startCellId==0)
1818     {
1819       for(int i=0;i<nbOfCells;i++)
1820         {
1821           if(!isFetched[i])
1822             {
1823               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1824               std::vector<int> v,v2;
1825               if(connOfNode!=connPtr+connIPtr[i+1])
1826                 {
1827                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1828                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1829                   connOfNode++;
1830                 }
1831               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1832                 if(*connOfNode>=0)
1833                   {
1834                     v=v2;
1835                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1836                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1837                     v2.resize(std::distance(v2.begin(),it));
1838                   }
1839               if(v2.size()>1)
1840                 {
1841                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1842                     {
1843                       int pos=commonCellsI->back();
1844                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1845                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1846                         isFetched[*it]=true;
1847                     }
1848                 }
1849             }
1850         }
1851     }
1852   else
1853     {
1854       for(int i=startCellId;i<nbOfCells;i++)
1855         {
1856           if(!isFetched[i])
1857             {
1858               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1859               std::vector<int> v,v2;
1860               if(connOfNode!=connPtr+connIPtr[i+1])
1861                 {
1862                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1863                   connOfNode++;
1864                 }
1865               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1866                 if(*connOfNode>=0)
1867                   {
1868                     v=v2;
1869                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1870                     v2.resize(std::distance(v2.begin(),it));
1871                   }
1872               if(v2.size()>1)
1873                 {
1874                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1875                     {
1876                       int pos=commonCellsI->back();
1877                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1878                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1879                         isFetched[*it]=true;
1880                     }
1881                 }
1882             }
1883         }
1884     }
1885   commonCellsArr=commonCells.retn();
1886   commonCellsIArr=commonCellsI.retn();
1887 }
1888
1889 /*!
1890  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1891  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1892  * than \a other->getNumberOfCells() in the returned array means that there is no
1893  * corresponding cell in \a this mesh.
1894  * It is expected that \a this and \a other meshes share the same node coordinates
1895  * array, if it is not so an exception is thrown. 
1896  *  \param [in] other - the mesh to compare with.
1897  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1898  *         valid values [0,1,2], see zipConnectivityTraducer().
1899  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1900  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1901  *         values. The caller is to delete this array using
1902  *         decrRef() as it is no more needed.
1903  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1904  *         mesh.
1905  *
1906  *  \if ENABLE_EXAMPLES
1907  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1908  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1909  *  \endif
1910  *  \sa checkDeepEquivalOnSameNodesWith()
1911  *  \sa checkGeoEquivalWith()
1912  */
1913 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1914 {
1915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1916   int nbOfCells=getNumberOfCells();
1917   static const int possibleCompType[]={0,1,2};
1918   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1919     {
1920       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1921       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1922       oss << " !";
1923       throw INTERP_KERNEL::Exception(oss.str().c_str());
1924     }
1925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1926   arr=o2n->substr(nbOfCells);
1927   arr->setName(other->getName());
1928   int tmp;
1929   if(other->getNumberOfCells()==0)
1930     return true;
1931   return arr->getMaxValue(tmp)<nbOfCells;
1932 }
1933
1934 /*!
1935  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1936  * This method tries to determine if \b other is fully included in \b this.
1937  * The main difference is that this method is not expected to throw exception.
1938  * This method has two outputs :
1939  *
1940  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1941  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1942  */
1943 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1944 {
1945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946   DataArrayInt *commonCells=0,*commonCellsI=0;
1947   int thisNbCells=getNumberOfCells();
1948   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1950   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1951   int otherNbCells=other->getNumberOfCells();
1952   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1953   arr2->alloc(otherNbCells,1);
1954   arr2->fillWithZero();
1955   int *arr2Ptr=arr2->getPointer();
1956   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1957   for(int i=0;i<nbOfCommon;i++)
1958     {
1959       int start=commonCellsPtr[commonCellsIPtr[i]];
1960       if(start<thisNbCells)
1961         {
1962           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1963             {
1964               int sig=commonCellsPtr[j]>0?1:-1;
1965               int val=std::abs(commonCellsPtr[j])-1;
1966               if(val>=thisNbCells)
1967                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1968             }
1969         }
1970     }
1971   arr2->setName(other->getName());
1972   if(arr2->presenceOfValue(0))
1973     return false;
1974   arr=arr2.retn();
1975   return true;
1976 }
1977
1978 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1979 {
1980   if(!other)
1981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1982   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1983   if(!otherC)
1984     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1985   std::vector<const MEDCouplingUMesh *> ms(2);
1986   ms[0]=this;
1987   ms[1]=otherC;
1988   return MergeUMeshesOnSameCoords(ms);
1989 }
1990
1991 /*!
1992  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1993  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1994  * cellIds is not given explicitely but by a range python like.
1995  * 
1996  * \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.
1997  * \return a newly allocated
1998  * 
1999  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2000  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2001  */
2002 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2003 {
2004   if(getMeshDimension()!=-1)
2005     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2006   else
2007     {
2008       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2009       if(newNbOfCells!=1)
2010         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2011       if(start!=0)
2012         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2013       incrRef();
2014       return const_cast<MEDCouplingUMesh *>(this);
2015     }
2016 }
2017
2018 /*!
2019  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2020  * The result mesh shares or not the node coordinates array with \a this mesh depending
2021  * on \a keepCoords parameter.
2022  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2023  *           to write this mesh to the MED file, its cells must be sorted using
2024  *           sortCellsInMEDFileFrmt().
2025  *  \param [in] begin - an array of cell ids to include to the new mesh.
2026  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2027  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2028  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2029  *         by calling zipCoords().
2030  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2031  *         to delete this mesh using decrRef() as it is no more needed. 
2032  *  \throw If the coordinates array is not set.
2033  *  \throw If the nodal connectivity of cells is not defined.
2034  *  \throw If any cell id in the array \a begin is not valid.
2035  *
2036  *  \if ENABLE_EXAMPLES
2037  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2038  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2039  *  \endif
2040  */
2041 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2042 {
2043   if(getMeshDimension()!=-1)
2044     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2045   else
2046     {
2047       if(end-begin!=1)
2048         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2049       if(begin[0]!=0)
2050         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2051       incrRef();
2052       return const_cast<MEDCouplingUMesh *>(this);
2053     }
2054 }
2055
2056 /*!
2057  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2058  *
2059  * 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.
2060  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2061  * The number of cells of \b this will remain the same with this method.
2062  *
2063  * \param [in] begin begin of cell ids (included) of cells in this to assign
2064  * \param [in] end end of cell ids (excluded) of cells in this to assign
2065  * \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 ).
2066  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2067  */
2068 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2069 {
2070   checkConnectivityFullyDefined();
2071   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2072   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2074   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2075     {
2076       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2077       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2078       throw INTERP_KERNEL::Exception(oss.str().c_str());
2079     }
2080   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2081   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2082     {
2083       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2084       throw INTERP_KERNEL::Exception(oss.str().c_str());
2085     }
2086   int nbOfCells=getNumberOfCells();
2087   bool easyAssign=true;
2088   const int *connI=_nodal_connec_index->getConstPointer();
2089   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2091     {
2092       if(*it>=0 && *it<nbOfCells)
2093         {
2094           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2095         }
2096       else
2097         {
2098           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2099           throw INTERP_KERNEL::Exception(oss.str().c_str());
2100         }
2101     }
2102   if(easyAssign)
2103     {
2104       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2105       computeTypes();
2106     }
2107   else
2108     {
2109       DataArrayInt *arrOut=0,*arrIOut=0;
2110       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2111                                                arrOut,arrIOut);
2112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113       setConnectivity(arrOut,arrIOut,true);
2114     }
2115 }
2116
2117 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2118 {
2119   checkConnectivityFullyDefined();
2120   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2121   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2123   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2124     {
2125       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2126       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2127       throw INTERP_KERNEL::Exception(oss.str().c_str());
2128     }
2129   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2130   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2131     {
2132       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2133       throw INTERP_KERNEL::Exception(oss.str().c_str());
2134     }
2135   int nbOfCells=getNumberOfCells();
2136   bool easyAssign=true;
2137   const int *connI=_nodal_connec_index->getConstPointer();
2138   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2139   int it=start;
2140   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2141     {
2142       if(it>=0 && it<nbOfCells)
2143         {
2144           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2145         }
2146       else
2147         {
2148           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2149           throw INTERP_KERNEL::Exception(oss.str().c_str());
2150         }
2151     }
2152   if(easyAssign)
2153     {
2154       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2155       computeTypes();
2156     }
2157   else
2158     {
2159       DataArrayInt *arrOut=0,*arrIOut=0;
2160       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2161                                                 arrOut,arrIOut);
2162       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2163       setConnectivity(arrOut,arrIOut,true);
2164     }
2165 }                      
2166
2167 /*!
2168  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2169  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2170  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2171  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2172  *
2173  * \param [in] begin input start of array of node ids.
2174  * \param [in] end input end of array of node ids.
2175  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2176  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2177  */
2178 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2179 {
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2181   checkConnectivityFullyDefined();
2182   int tmp=-1;
2183   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2184   std::vector<bool> fastFinder(sz,false);
2185   for(const int *work=begin;work!=end;work++)
2186     if(*work>=0 && *work<sz)
2187       fastFinder[*work]=true;
2188   int nbOfCells=getNumberOfCells();
2189   const int *conn=getNodalConnectivity()->getConstPointer();
2190   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2191   for(int i=0;i<nbOfCells;i++)
2192     {
2193       int ref=0,nbOfHit=0;
2194       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2195         if(*work2>=0)
2196           {
2197             ref++;
2198             if(fastFinder[*work2])
2199               nbOfHit++;
2200           }
2201       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2202         cellIdsKept->pushBackSilent(i);
2203     }
2204   cellIdsKeptArr=cellIdsKept.retn();
2205 }
2206
2207 /*!
2208  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2209  * this->getMeshDimension(), that bound some cells of \a this mesh.
2210  * The cells of lower dimension to include to the result mesh are selected basing on
2211  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2212  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2213  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2214  * created mesh shares the node coordinates array with \a this mesh. 
2215  *  \param [in] begin - the array of node ids.
2216  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2217  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2218  *         array \a begin are added, else cells whose any node is in the
2219  *         array \a begin are added.
2220  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2221  *         to delete this mesh using decrRef() as it is no more needed. 
2222  *  \throw If the coordinates array is not set.
2223  *  \throw If the nodal connectivity of cells is not defined.
2224  *  \throw If any node id in \a begin is not valid.
2225  *
2226  *  \if ENABLE_EXAMPLES
2227  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2228  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2229  *  \endif
2230  */
2231 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2232 {
2233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2234   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2236   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2237   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2238 }
2239
2240 /*!
2241  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2243  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2244  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2245  *         by calling zipCoords().
2246  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2247  *         to delete this mesh using decrRef() as it is no more needed. 
2248  *  \throw If the coordinates array is not set.
2249  *  \throw If the nodal connectivity of cells is not defined.
2250  *
2251  *  \if ENABLE_EXAMPLES
2252  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2253  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2254  *  \endif
2255  */
2256 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2257 {
2258   DataArrayInt *desc=DataArrayInt::New();
2259   DataArrayInt *descIndx=DataArrayInt::New();
2260   DataArrayInt *revDesc=DataArrayInt::New();
2261   DataArrayInt *revDescIndx=DataArrayInt::New();
2262   //
2263   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2264   revDesc->decrRef();
2265   desc->decrRef();
2266   descIndx->decrRef();
2267   int nbOfCells=meshDM1->getNumberOfCells();
2268   const int *revDescIndxC=revDescIndx->getConstPointer();
2269   std::vector<int> boundaryCells;
2270   for(int i=0;i<nbOfCells;i++)
2271     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2272       boundaryCells.push_back(i);
2273   revDescIndx->decrRef();
2274   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2275   return ret;
2276 }
2277
2278 /*!
2279  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2280  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2281  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2282  */
2283 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2284 {
2285   checkFullyDefined();
2286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2290   //
2291   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2292   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2293   //
2294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2296   const int *revDescPtr=revDesc->getConstPointer();
2297   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2298   int nbOfCells=getNumberOfCells();
2299   std::vector<bool> ret1(nbOfCells,false);
2300   int sz=0;
2301   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2302     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2303       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2304   //
2305   DataArrayInt *ret2=DataArrayInt::New();
2306   ret2->alloc(sz,1);
2307   int *ret2Ptr=ret2->getPointer();
2308   sz=0;
2309   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2310     if(*it)
2311       *ret2Ptr++=sz;
2312   ret2->setName("BoundaryCells");
2313   return ret2;
2314 }
2315
2316 /*!
2317  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2318  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2319  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2320  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2321  *
2322  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2323  * This method method returns cells ids set s = s1 + s2 where :
2324  * 
2325  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2326  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2327  *
2328  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2329  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2330  *
2331  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2332  * \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
2333  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2334  */
2335 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2336 {
2337   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2338     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2339   checkConnectivityFullyDefined();
2340   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2341   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2348   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2349   DataArrayInt *idsOtherInConsti=0;
2350   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2352   if(!b)
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2354   std::set<int> s1;
2355   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2356     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2359   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2360   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2362   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2363   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2364   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2365   neighThisPartAuto=0;
2366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2367   const int li[2]={0,1};
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2369   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2371   s_renum1->sort();
2372   //
2373   cellIdsRk0=s0arr.retn();
2374   cellIdsRk1=s_renum1.retn();
2375 }
2376
2377 /*!
2378  * 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
2379  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2380  * 
2381  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2382  */
2383 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2384 {
2385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2389   //
2390   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2391   revDesc=0; desc=0; descIndx=0;
2392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2394   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2395 }
2396
2397 /*!
2398  * Finds nodes lying on the boundary of \a this mesh.
2399  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2400  *          nodes. The caller is to delete this array using decrRef() as it is no
2401  *          more needed.
2402  *  \throw If the coordinates array is not set.
2403  *  \throw If the nodal connectivity of cells is node defined.
2404  *
2405  *  \if ENABLE_EXAMPLES
2406  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2407  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2408  *  \endif
2409  */
2410 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2411 {
2412   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2413   return skin->computeFetchedNodeIds();
2414 }
2415
2416 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2417 {
2418   incrRef();
2419   return const_cast<MEDCouplingUMesh *>(this);
2420 }
2421
2422 /*!
2423  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2424  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2425  * 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.
2426  * 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.
2427  * 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.
2428  *
2429  * \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
2430  *             parameter is altered during the call.
2431  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2432  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2433  * \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.
2434  *
2435  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2436  */
2437 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2438                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2439 {
2440   checkFullyDefined();
2441   otherDimM1OnSameCoords.checkFullyDefined();
2442   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2444   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2446   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2447   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2450   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2451   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2455   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2456   //
2457   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2459   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2460   DataArrayInt *idsTmp=0;
2461   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2463   if(!b)
2464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2465   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2466   DataArrayInt *tmp0=0,*tmp1=0;
2467   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2472   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2473   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2474   //
2475   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2476   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2477   nodeIdsToDuplicate=s3.retn();
2478 }
2479
2480 /*!
2481  * This method operates a modification of the connectivity and coords in \b this.
2482  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2483  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2484  * 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
2485  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2486  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2487  * 
2488  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2489  * 
2490  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2492  */
2493 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2494 {
2495   int nbOfNodes=getNumberOfNodes();
2496   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2497   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2498 }
2499
2500 /*!
2501  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2502  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2503  *  of a big mesh.
2504  */
2505 void MEDCouplingUMesh::renumberNodesInConn(const std::map<int,int>& newNodeNumbersO2N)
2506 {
2507   checkConnectivityFullyDefined();
2508   int *conn(getNodalConnectivity()->getPointer());
2509   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2510   int nbOfCells=getNumberOfCells();
2511   for(int i=0;i<nbOfCells;i++)
2512     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2513       {
2514         int& node=conn[iconn];
2515         if(node>=0)//avoid polyhedron separator
2516           {
2517             std::map<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2518             if(it!=newNodeNumbersO2N.end())
2519               {
2520                 node=(*it).second;
2521               }
2522             else
2523               {
2524                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2525                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2526               }
2527           }
2528       }
2529   _nodal_connec->declareAsNew();
2530   updateTime();
2531 }
2532
2533 /*!
2534  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2535  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2536  * This method is a generalization of shiftNodeNumbersInConn().
2537  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2538  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2539  *         this->getNumberOfNodes(), in "Old to New" mode. 
2540  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2541  *  \throw If the nodal connectivity of cells is not defined.
2542  *
2543  *  \if ENABLE_EXAMPLES
2544  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2545  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2546  *  \endif
2547  */
2548 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2549 {
2550   checkConnectivityFullyDefined();
2551   int *conn=getNodalConnectivity()->getPointer();
2552   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2553   int nbOfCells=getNumberOfCells();
2554   for(int i=0;i<nbOfCells;i++)
2555     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2556       {
2557         int& node=conn[iconn];
2558         if(node>=0)//avoid polyhedron separator
2559           {
2560             node=newNodeNumbersO2N[node];
2561           }
2562       }
2563   _nodal_connec->declareAsNew();
2564   updateTime();
2565 }
2566
2567 /*!
2568  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2569  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2570  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2571  * 
2572  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2573  */
2574 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2575 {
2576   checkConnectivityFullyDefined();
2577   int *conn=getNodalConnectivity()->getPointer();
2578   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2579   int nbOfCells=getNumberOfCells();
2580   for(int i=0;i<nbOfCells;i++)
2581     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2582       {
2583         int& node=conn[iconn];
2584         if(node>=0)//avoid polyhedron separator
2585           {
2586             node+=delta;
2587           }
2588       }
2589   _nodal_connec->declareAsNew();
2590   updateTime();
2591 }
2592
2593 /*!
2594  * This method operates a modification of the connectivity in \b this.
2595  * 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.
2596  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2597  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2598  * 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
2599  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2600  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2601  * 
2602  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2603  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2604  * 
2605  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2606  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2607  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2608  */
2609 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2610 {
2611   checkConnectivityFullyDefined();
2612   std::map<int,int> m;
2613   int val=offset;
2614   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2615     m[*work]=val;
2616   int *conn=getNodalConnectivity()->getPointer();
2617   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2618   int nbOfCells=getNumberOfCells();
2619   for(int i=0;i<nbOfCells;i++)
2620     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2621       {
2622         int& node=conn[iconn];
2623         if(node>=0)//avoid polyhedron separator
2624           {
2625             std::map<int,int>::iterator it=m.find(node);
2626             if(it!=m.end())
2627               node=(*it).second;
2628           }
2629       }
2630   updateTime();
2631 }
2632
2633 /*!
2634  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2635  *
2636  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2637  * After the call of this method the number of cells remains the same as before.
2638  *
2639  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2640  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2641  * be strictly in [0;this->getNumberOfCells()).
2642  *
2643  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2644  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2645  * should be contained in[0;this->getNumberOfCells()).
2646  * 
2647  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2648  */
2649 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2650 {
2651   checkConnectivityFullyDefined();
2652   int nbCells=getNumberOfCells();
2653   const int *array=old2NewBg;
2654   if(check)
2655     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2656   //
2657   const int *conn=_nodal_connec->getConstPointer();
2658   const int *connI=_nodal_connec_index->getConstPointer();
2659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2661   const int *n2oPtr=n2o->begin();
2662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2663   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2664   newConn->copyStringInfoFrom(*_nodal_connec);
2665   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2666   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2667   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2668   //
2669   int *newC=newConn->getPointer();
2670   int *newCI=newConnI->getPointer();
2671   int loc=0;
2672   newCI[0]=loc;
2673   for(int i=0;i<nbCells;i++)
2674     {
2675       int pos=n2oPtr[i];
2676       int nbOfElts=connI[pos+1]-connI[pos];
2677       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2678       loc+=nbOfElts;
2679       newCI[i+1]=loc;
2680     }
2681   //
2682   setConnectivity(newConn,newConnI);
2683   if(check)
2684     free(const_cast<int *>(array));
2685 }
2686
2687 /*!
2688  * Finds cells whose bounding boxes intersect a given bounding box.
2689  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2690  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2691  *         zMax (if in 3D). 
2692  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2693  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2694  *         extent of the bounding box of cell to produce an addition to this bounding box.
2695  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2696  *         cells. The caller is to delete this array using decrRef() as it is no more
2697  *         needed. 
2698  *  \throw If the coordinates array is not set.
2699  *  \throw If the nodal connectivity of cells is not defined.
2700  *
2701  *  \if ENABLE_EXAMPLES
2702  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2703  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2704  *  \endif
2705  */
2706 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2707 {
2708   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2709   if(getMeshDimension()==-1)
2710     {
2711       elems->pushBackSilent(0);
2712       return elems.retn();
2713     }
2714   int dim=getSpaceDimension();
2715   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2716   const int* conn      = getNodalConnectivity()->getConstPointer();
2717   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2718   const double* coords = getCoords()->getConstPointer();
2719   int nbOfCells=getNumberOfCells();
2720   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2721     {
2722       for (int i=0; i<dim; i++)
2723         {
2724           elem_bb[i*2]=std::numeric_limits<double>::max();
2725           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2726         }
2727
2728       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2729         {
2730           int node= conn[inode];
2731           if(node>=0)//avoid polyhedron separator
2732             {
2733               for (int idim=0; idim<dim; idim++)
2734                 {
2735                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2736                     {
2737                       elem_bb[idim*2] = coords[node*dim+idim] ;
2738                     }
2739                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2740                     {
2741                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2742                     }
2743                 }
2744             }
2745         }
2746       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2747         elems->pushBackSilent(ielem);
2748     }
2749   return elems.retn();
2750 }
2751
2752 /*!
2753  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2754  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2755  * added in 'elems' parameter.
2756  */
2757 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2758 {
2759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2760   if(getMeshDimension()==-1)
2761     {
2762       elems->pushBackSilent(0);
2763       return elems.retn();
2764     }
2765   int dim=getSpaceDimension();
2766   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2767   const int* conn      = getNodalConnectivity()->getConstPointer();
2768   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2769   const double* coords = getCoords()->getConstPointer();
2770   int nbOfCells=getNumberOfCells();
2771   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2772     {
2773       for (int i=0; i<dim; i++)
2774         {
2775           elem_bb[i*2]=std::numeric_limits<double>::max();
2776           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2777         }
2778
2779       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2780         {
2781           int node= conn[inode];
2782           if(node>=0)//avoid polyhedron separator
2783             {
2784               for (int idim=0; idim<dim; idim++)
2785                 {
2786                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2787                     {
2788                       elem_bb[idim*2] = coords[node*dim+idim] ;
2789                     }
2790                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2791                     {
2792                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2793                     }
2794                 }
2795             }
2796         }
2797       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2798         elems->pushBackSilent(ielem);
2799     }
2800   return elems.retn();
2801 }
2802
2803 /*!
2804  * Returns a type of a cell by its id.
2805  *  \param [in] cellId - the id of the cell of interest.
2806  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2807  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2808  */
2809 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2810 {
2811   const int *ptI=_nodal_connec_index->getConstPointer();
2812   const int *pt=_nodal_connec->getConstPointer();
2813   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2814     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2815   else
2816     {
2817       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2818       throw INTERP_KERNEL::Exception(oss.str().c_str());
2819     }
2820 }
2821
2822 /*!
2823  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2824  * This method does not throw exception if geometric type \a type is not in \a this.
2825  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2826  * The coordinates array is not considered here.
2827  *
2828  * \param [in] type the geometric type
2829  * \return cell ids in this having geometric type \a type.
2830  */
2831 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2832 {
2833
2834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2835   ret->alloc(0,1);
2836   checkConnectivityFullyDefined();
2837   int nbCells=getNumberOfCells();
2838   int mdim=getMeshDimension();
2839   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2840   if(mdim!=(int)cm.getDimension())
2841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2842   const int *ptI=_nodal_connec_index->getConstPointer();
2843   const int *pt=_nodal_connec->getConstPointer();
2844   for(int i=0;i<nbCells;i++)
2845     {
2846       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2847         ret->pushBackSilent(i);
2848     }
2849   return ret.retn();
2850 }
2851
2852 /*!
2853  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2854  */
2855 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2856 {
2857   const int *ptI=_nodal_connec_index->getConstPointer();
2858   const int *pt=_nodal_connec->getConstPointer();
2859   int nbOfCells=getNumberOfCells();
2860   int ret=0;
2861   for(int i=0;i<nbOfCells;i++)
2862     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2863       ret++;
2864   return ret;
2865 }
2866
2867 /*!
2868  * Returns the nodal connectivity of a given cell.
2869  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2870  * all returned node ids can be used in getCoordinatesOfNode().
2871  *  \param [in] cellId - an id of the cell of interest.
2872  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2873  *         cleared before the appending.
2874  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2875  */
2876 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2877 {
2878   const int *ptI=_nodal_connec_index->getConstPointer();
2879   const int *pt=_nodal_connec->getConstPointer();
2880   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2881     if(*w>=0)
2882       conn.push_back(*w);
2883 }
2884
2885 std::string MEDCouplingUMesh::simpleRepr() const
2886 {
2887   static const char msg0[]="No coordinates specified !";
2888   std::ostringstream ret;
2889   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2890   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2891   int tmpp1,tmpp2;
2892   double tt=getTime(tmpp1,tmpp2);
2893   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2894   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2895   if(_mesh_dim>=-1)
2896     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2897   else
2898     { ret << " Mesh dimension has not been set or is invalid !"; }
2899   if(_coords!=0)
2900     {
2901       const int spaceDim=getSpaceDimension();
2902       ret << spaceDim << "\nInfo attached on space dimension : ";
2903       for(int i=0;i<spaceDim;i++)
2904         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2905       ret << "\n";
2906     }
2907   else
2908     ret << msg0 << "\n";
2909   ret << "Number of nodes : ";
2910   if(_coords!=0)
2911     ret << getNumberOfNodes() << "\n";
2912   else
2913     ret << msg0 << "\n";
2914   ret << "Number of cells : ";
2915   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2916     ret << getNumberOfCells() << "\n";
2917   else
2918     ret << "No connectivity specified !" << "\n";
2919   ret << "Cell types present : ";
2920   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2921     {
2922       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2923       ret << cm.getRepr() << " ";
2924     }
2925   ret << "\n";
2926   return ret.str();
2927 }
2928
2929 std::string MEDCouplingUMesh::advancedRepr() const
2930 {
2931   std::ostringstream ret;
2932   ret << simpleRepr();
2933   ret << "\nCoordinates array : \n___________________\n\n";
2934   if(_coords)
2935     _coords->reprWithoutNameStream(ret);
2936   else
2937     ret << "No array set !\n";
2938   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2939   reprConnectivityOfThisLL(ret);
2940   return ret.str();
2941 }
2942
2943 /*!
2944  * This method returns a C++ code that is a dump of \a this.
2945  * This method will throw if this is not fully defined.
2946  */
2947 std::string MEDCouplingUMesh::cppRepr() const
2948 {
2949   static const char coordsName[]="coords";
2950   static const char connName[]="conn";
2951   static const char connIName[]="connI";
2952   checkFullyDefined();
2953   std::ostringstream ret; ret << "// coordinates" << std::endl;
2954   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2955   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2956   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2957   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2958   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2959   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2960   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2961   return ret.str();
2962 }
2963
2964 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2965 {
2966   std::ostringstream ret;
2967   reprConnectivityOfThisLL(ret);
2968   return ret.str();
2969 }
2970
2971 /*!
2972  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2973  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2974  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2975  * some algos).
2976  * 
2977  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2978  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
2979  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2980  */
2981 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2982 {
2983   int mdim=getMeshDimension();
2984   if(mdim<0)
2985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2986   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2988   bool needToCpyCT=true;
2989   if(!_nodal_connec)
2990     {
2991       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2992       needToCpyCT=false;
2993     }
2994   else
2995     {
2996       tmp1=_nodal_connec;
2997       tmp1->incrRef();
2998     }
2999   if(!_nodal_connec_index)
3000     {
3001       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3002       needToCpyCT=false;
3003     }
3004   else
3005     {
3006       tmp2=_nodal_connec_index;
3007       tmp2->incrRef();
3008     }
3009   ret->setConnectivity(tmp1,tmp2,false);
3010   if(needToCpyCT)
3011     ret->_types=_types;
3012   if(!_coords)
3013     {
3014       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3015       ret->setCoords(coords);
3016     }
3017   else
3018     ret->setCoords(_coords);
3019   return ret.retn();
3020 }
3021
3022 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3023 {
3024   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3025     {
3026       int nbOfCells=getNumberOfCells();
3027       const int *c=_nodal_connec->getConstPointer();
3028       const int *ci=_nodal_connec_index->getConstPointer();
3029       for(int i=0;i<nbOfCells;i++)
3030         {
3031           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3032           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3033           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3034           stream << "\n";
3035         }
3036     }
3037   else
3038     stream << "Connectivity not defined !\n";
3039 }
3040
3041 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3042 {
3043   const int *ptI=_nodal_connec_index->getConstPointer();
3044   const int *pt=_nodal_connec->getConstPointer();
3045   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3046     return ptI[cellId+1]-ptI[cellId]-1;
3047   else
3048     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3049 }
3050
3051 /*!
3052  * Returns types of cells of the specified part of \a this mesh.
3053  * This method avoids computing sub-mesh explicitely to get its types.
3054  *  \param [in] begin - an array of cell ids of interest.
3055  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3056  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3057  *         describing the cell types. 
3058  *  \throw If the coordinates array is not set.
3059  *  \throw If the nodal connectivity of cells is not defined.
3060  *  \sa getAllGeoTypes()
3061  */
3062 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3063 {
3064   checkFullyDefined();
3065   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3066   const int *conn=_nodal_connec->getConstPointer();
3067   const int *connIndex=_nodal_connec_index->getConstPointer();
3068   for(const int *w=begin;w!=end;w++)
3069     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3070   return ret;
3071 }
3072
3073 /*!
3074  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3075  * a set of types of cells constituting \a this mesh. 
3076  * This method is for advanced users having prepared their connectivity before. For
3077  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3078  *  \param [in] conn - the nodal connectivity array. 
3079  *  \param [in] connIndex - the nodal connectivity index array.
3080  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3081  *         mesh is updated.
3082  */
3083 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3084 {
3085   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3086   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3087   if(isComputingTypes)
3088     computeTypes();
3089   declareAsNew();
3090 }
3091
3092 /*!
3093  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3094  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3095  */
3096 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3097     _nodal_connec(0),_nodal_connec_index(0),
3098     _types(other._types)
3099 {
3100   if(other._nodal_connec)
3101     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3102   if(other._nodal_connec_index)
3103     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3104 }
3105
3106 MEDCouplingUMesh::~MEDCouplingUMesh()
3107 {
3108   if(_nodal_connec)
3109     _nodal_connec->decrRef();
3110   if(_nodal_connec_index)
3111     _nodal_connec_index->decrRef();
3112 }
3113
3114 /*!
3115  * Recomputes a set of cell types of \a this mesh. For more info see
3116  * \ref MEDCouplingUMeshNodalConnectivity.
3117  */
3118 void MEDCouplingUMesh::computeTypes()
3119 {
3120   if(_nodal_connec && _nodal_connec_index)
3121     {
3122       _types.clear();
3123       const int *conn=_nodal_connec->getConstPointer();
3124       const int *connIndex=_nodal_connec_index->getConstPointer();
3125       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3126       if (nbOfElem > 0)
3127         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3128           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3129     }
3130 }
3131
3132 /*!
3133  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3134  */
3135 void MEDCouplingUMesh::checkFullyDefined() const
3136 {
3137   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3138     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3139 }
3140
3141 /*!
3142  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3143  */
3144 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3145 {
3146   if(!_nodal_connec_index || !_nodal_connec)
3147     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3148 }
3149
3150 /*!
3151  * Returns a number of cells constituting \a this mesh. 
3152  *  \return int - the number of cells in \a this mesh.
3153  *  \throw If the nodal connectivity of cells is not defined.
3154  */
3155 int MEDCouplingUMesh::getNumberOfCells() const
3156
3157   if(_nodal_connec_index)
3158     return _nodal_connec_index->getNumberOfTuples()-1;
3159   else
3160     if(_mesh_dim==-1)
3161       return 1;
3162     else
3163       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3164 }
3165
3166 /*!
3167  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3168  * mesh. For more info see \ref MEDCouplingMeshesPage.
3169  *  \return int - the dimension of \a this mesh.
3170  *  \throw If the mesh dimension is not defined using setMeshDimension().
3171  */
3172 int MEDCouplingUMesh::getMeshDimension() const
3173 {
3174   if(_mesh_dim<-1)
3175     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3176   return _mesh_dim;
3177 }
3178
3179 /*!
3180  * Returns a length of the nodal connectivity array.
3181  * This method is for test reason. Normally the integer returned is not useable by
3182  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3183  *  \return int - the length of the nodal connectivity array.
3184  */
3185 int MEDCouplingUMesh::getMeshLength() const
3186 {
3187   return _nodal_connec->getNbOfElems();
3188 }
3189
3190 /*!
3191  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3192  */
3193 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3194 {
3195   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3196   tinyInfo.push_back(getMeshDimension());
3197   tinyInfo.push_back(getNumberOfCells());
3198   if(_nodal_connec)
3199     tinyInfo.push_back(getMeshLength());
3200   else
3201     tinyInfo.push_back(-1);
3202 }
3203
3204 /*!
3205  * First step of unserialization process.
3206  */
3207 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3208 {
3209   return tinyInfo[6]<=0;
3210 }
3211
3212 /*!
3213  * Second step of serialization process.
3214  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3215  */
3216 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3217 {
3218   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3219   if(tinyInfo[5]!=-1)
3220     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3221 }
3222
3223 /*!
3224  * Third and final step of serialization process.
3225  */
3226 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3227 {
3228   MEDCouplingPointSet::serialize(a1,a2);
3229   if(getMeshDimension()>-1)
3230     {
3231       a1=DataArrayInt::New();
3232       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3233       int *ptA1=a1->getPointer();
3234       const int *conn=getNodalConnectivity()->getConstPointer();
3235       const int *index=getNodalConnectivityIndex()->getConstPointer();
3236       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3237       std::copy(conn,conn+getMeshLength(),ptA1);
3238     }
3239   else
3240     a1=0;
3241 }
3242
3243 /*!
3244  * Second and final unserialization process.
3245  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3246  */
3247 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3248 {
3249   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3250   setMeshDimension(tinyInfo[5]);
3251   if(tinyInfo[7]!=-1)
3252     {
3253       // Connectivity
3254       const int *recvBuffer=a1->getConstPointer();
3255       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3256       myConnecIndex->alloc(tinyInfo[6]+1,1);
3257       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3258       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3259       myConnec->alloc(tinyInfo[7],1);
3260       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3261       setConnectivity(myConnec, myConnecIndex);
3262     }
3263 }
3264
3265 /*!
3266  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3267  * CellIds are given using range specified by a start an end and step.
3268  */
3269 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3270 {
3271   checkFullyDefined();
3272   int ncell=getNumberOfCells();
3273   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3274   ret->_mesh_dim=_mesh_dim;
3275   ret->setCoords(_coords);
3276   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3278   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3279   int work=start;
3280   const int *conn=_nodal_connec->getConstPointer();
3281   const int *connIndex=_nodal_connec_index->getConstPointer();
3282   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3283     {
3284       if(work>=0 && work<ncell)
3285         {
3286           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3287         }
3288       else
3289         {
3290           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3291           throw INTERP_KERNEL::Exception(oss.str().c_str());
3292         }
3293     }
3294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3295   int *newConnPtr=newConn->getPointer();
3296   std::set<INTERP_KERNEL::NormalizedCellType> types;
3297   work=start;
3298   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3299     {
3300       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3301       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3302     }
3303   ret->setConnectivity(newConn,newConnI,false);
3304   ret->_types=types;
3305   ret->copyTinyInfoFrom(this);
3306   return ret.retn();
3307 }
3308
3309 /*!
3310  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3311  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3312  * The return newly allocated mesh will share the same coordinates as \a this.
3313  */
3314 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3315 {
3316   checkConnectivityFullyDefined();
3317   int ncell=getNumberOfCells();
3318   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3319   ret->_mesh_dim=_mesh_dim;
3320   ret->setCoords(_coords);
3321   std::size_t nbOfElemsRet=std::distance(begin,end);
3322   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3323   connIndexRet[0]=0;
3324   const int *conn=_nodal_connec->getConstPointer();
3325   const int *connIndex=_nodal_connec_index->getConstPointer();
3326   int newNbring=0;
3327   for(const int *work=begin;work!=end;work++,newNbring++)
3328     {
3329       if(*work>=0 && *work<ncell)
3330         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3331       else
3332         {
3333           free(connIndexRet);
3334           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3335           throw INTERP_KERNEL::Exception(oss.str().c_str());
3336         }
3337     }
3338   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3339   int *connRetWork=connRet;
3340   std::set<INTERP_KERNEL::NormalizedCellType> types;
3341   for(const int *work=begin;work!=end;work++)
3342     {
3343       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3344       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3345     }
3346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3347   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3349   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3350   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3351   ret->_types=types;
3352   ret->copyTinyInfoFrom(this);
3353   return ret.retn();
3354 }
3355
3356 /*!
3357  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3358  * mesh.<br>
3359  * For 1D cells, the returned field contains lengths.<br>
3360  * For 2D cells, the returned field contains areas.<br>
3361  * For 3D cells, the returned field contains volumes.
3362  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3363  *         orientation, i.e. the volume is always positive.
3364  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3365  *         and one time . The caller is to delete this field using decrRef() as it is no
3366  *         more needed.
3367  */
3368 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3369 {
3370   std::string name="MeasureOfMesh_";
3371   name+=getName();
3372   int nbelem=getNumberOfCells();
3373   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3374   field->setName(name);
3375   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3376   array->alloc(nbelem,1);
3377   double *area_vol=array->getPointer();
3378   field->setArray(array) ; array=0;
3379   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3380   field->synchronizeTimeWithMesh();
3381   if(getMeshDimension()!=-1)
3382     {
3383       int ipt;
3384       INTERP_KERNEL::NormalizedCellType type;
3385       int dim_space=getSpaceDimension();
3386       const double *coords=getCoords()->getConstPointer();
3387       const int *connec=getNodalConnectivity()->getConstPointer();
3388       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3389       for(int iel=0;iel<nbelem;iel++)
3390         {
3391           ipt=connec_index[iel];
3392           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3393           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);
3394         }
3395       if(isAbs)
3396         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3397     }
3398   else
3399     {
3400       area_vol[0]=std::numeric_limits<double>::max();
3401     }
3402   return field.retn();
3403 }
3404
3405 /*!
3406  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3407  * mesh.<br>
3408  * For 1D cells, the returned array contains lengths.<br>
3409  * For 2D cells, the returned array contains areas.<br>
3410  * For 3D cells, the returned array contains volumes.
3411  * This method avoids building explicitly a part of \a this mesh to perform the work.
3412  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3413  *         orientation, i.e. the volume is always positive.
3414  *  \param [in] begin - an array of cell ids of interest.
3415  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3416  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3417  *          delete this array using decrRef() as it is no more needed.
3418  * 
3419  *  \if ENABLE_EXAMPLES
3420  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3421  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3422  *  \endif
3423  *  \sa getMeasureField()
3424  */
3425 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3426 {
3427   std::string name="PartMeasureOfMesh_";
3428   name+=getName();
3429   int nbelem=(int)std::distance(begin,end);
3430   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3431   array->setName(name);
3432   array->alloc(nbelem,1);
3433   double *area_vol=array->getPointer();
3434   if(getMeshDimension()!=-1)
3435     {
3436       int ipt;
3437       INTERP_KERNEL::NormalizedCellType type;
3438       int dim_space=getSpaceDimension();
3439       const double *coords=getCoords()->getConstPointer();
3440       const int *connec=getNodalConnectivity()->getConstPointer();
3441       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3442       for(const int *iel=begin;iel!=end;iel++)
3443         {
3444           ipt=connec_index[*iel];
3445           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3446           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3447         }
3448       if(isAbs)
3449         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3450     }
3451   else
3452     {
3453       area_vol[0]=std::numeric_limits<double>::max();
3454     }
3455   return array.retn();
3456 }
3457
3458 /*!
3459  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3460  * \a this one. The returned field contains the dual cell volume for each corresponding
3461  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3462  *  the dual mesh in P1 sens of \a this.<br>
3463  * For 1D cells, the returned field contains lengths.<br>
3464  * For 2D cells, the returned field contains areas.<br>
3465  * For 3D cells, the returned field contains volumes.
3466  * This method is useful to check "P1*" conservative interpolators.
3467  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3468  *         orientation, i.e. the volume is always positive.
3469  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3470  *          nodes and one time. The caller is to delete this array using decrRef() as
3471  *          it is no more needed.
3472  */
3473 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3474 {
3475   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3476   std::string name="MeasureOnNodeOfMesh_";
3477   name+=getName();
3478   int nbNodes=getNumberOfNodes();
3479   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3480   double cst=1./((double)getMeshDimension()+1.);
3481   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3482   array->alloc(nbNodes,1);
3483   double *valsToFill=array->getPointer();
3484   std::fill(valsToFill,valsToFill+nbNodes,0.);
3485   const double *values=tmp->getArray()->getConstPointer();
3486   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3488   getReverseNodalConnectivity(da,daInd);
3489   const int *daPtr=da->getConstPointer();
3490   const int *daIPtr=daInd->getConstPointer();
3491   for(int i=0;i<nbNodes;i++)
3492     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3493       valsToFill[i]+=cst*values[*cell];
3494   ret->setMesh(this);
3495   ret->setArray(array);
3496   return ret.retn();
3497 }
3498
3499 /*!
3500  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3501  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3502  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3503  * and are normalized.
3504  * <br> \a this can be either 
3505  * - a  2D mesh in 2D or 3D space or 
3506  * - an 1D mesh in 2D space.
3507  * 
3508  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3509  *          cells and one time. The caller is to delete this field using decrRef() as
3510  *          it is no more needed.
3511  *  \throw If the nodal connectivity of cells is not defined.
3512  *  \throw If the coordinates array is not set.
3513  *  \throw If the mesh dimension is not set.
3514  *  \throw If the mesh and space dimension is not as specified above.
3515  */
3516 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3517 {
3518   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3519     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3520   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3521   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3522   int nbOfCells=getNumberOfCells();
3523   int nbComp=getMeshDimension()+1;
3524   array->alloc(nbOfCells,nbComp);
3525   double *vals=array->getPointer();
3526   const int *connI=_nodal_connec_index->getConstPointer();
3527   const int *conn=_nodal_connec->getConstPointer();
3528   const double *coords=_coords->getConstPointer();
3529   if(getMeshDimension()==2)
3530     {
3531       if(getSpaceDimension()==3)
3532         {
3533           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3534           const double *locPtr=loc->getConstPointer();
3535           for(int i=0;i<nbOfCells;i++,vals+=3)
3536             {
3537               int offset=connI[i];
3538               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3539               double n=INTERP_KERNEL::norm<3>(vals);
3540               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3541             }
3542         }
3543       else
3544         {
3545           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3546           const double *isAbsPtr=isAbs->getArray()->begin();
3547           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3548             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3549         }
3550     }
3551   else//meshdimension==1
3552     {
3553       double tmp[2];
3554       for(int i=0;i<nbOfCells;i++)
3555         {
3556           int offset=connI[i];
3557           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3558           double n=INTERP_KERNEL::norm<2>(tmp);
3559           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3560           *vals++=-tmp[1];
3561           *vals++=tmp[0];
3562         }
3563     }
3564   ret->setArray(array);
3565   ret->setMesh(this);
3566   ret->synchronizeTimeWithSupport();
3567   return ret.retn();
3568 }
3569
3570 /*!
3571  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3572  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3573  * and are normalized.
3574  * <br> \a this can be either 
3575  * - a  2D mesh in 2D or 3D space or 
3576  * - an 1D mesh in 2D space.
3577  * 
3578  * This method avoids building explicitly a part of \a this mesh to perform the work.
3579  *  \param [in] begin - an array of cell ids of interest.
3580  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3581  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3582  *          cells and one time. The caller is to delete this field using decrRef() as
3583  *          it is no more needed.
3584  *  \throw If the nodal connectivity of cells is not defined.
3585  *  \throw If the coordinates array is not set.
3586  *  \throw If the mesh dimension is not set.
3587  *  \throw If the mesh and space dimension is not as specified above.
3588  *  \sa buildOrthogonalField()
3589  *
3590  *  \if ENABLE_EXAMPLES
3591  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3592  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3593  *  \endif
3594  */
3595 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3596 {
3597   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3598     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3599   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3600   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3601   std::size_t nbelems=std::distance(begin,end);
3602   int nbComp=getMeshDimension()+1;
3603   array->alloc((int)nbelems,nbComp);
3604   double *vals=array->getPointer();
3605   const int *connI=_nodal_connec_index->getConstPointer();
3606   const int *conn=_nodal_connec->getConstPointer();
3607   const double *coords=_coords->getConstPointer();
3608   if(getMeshDimension()==2)
3609     {
3610       if(getSpaceDimension()==3)
3611         {
3612           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3613           const double *locPtr=loc->getConstPointer();
3614           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3615             {
3616               int offset=connI[*i];
3617               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3618               double n=INTERP_KERNEL::norm<3>(vals);
3619               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3620             }
3621         }
3622       else
3623         {
3624           for(std::size_t i=0;i<nbelems;i++)
3625             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3626         }
3627     }
3628   else//meshdimension==1
3629     {
3630       double tmp[2];
3631       for(const int *i=begin;i!=end;i++)
3632         {
3633           int offset=connI[*i];
3634           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3635           double n=INTERP_KERNEL::norm<2>(tmp);
3636           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3637           *vals++=-tmp[1];
3638           *vals++=tmp[0];
3639         }
3640     }
3641   ret->setArray(array);
3642   ret->setMesh(this);
3643   ret->synchronizeTimeWithSupport();
3644   return ret.retn();
3645 }
3646
3647 /*!
3648  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3649  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3650  * and are \b not normalized.
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 \a this->getMeshDimension() != 1.
3657  *  \throw If \a this mesh includes cells of type other than SEG2.
3658  */
3659 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3660 {
3661   if(getMeshDimension()!=1)
3662     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3663   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3664     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3665   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3666   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3667   int nbOfCells=getNumberOfCells();
3668   int spaceDim=getSpaceDimension();
3669   array->alloc(nbOfCells,spaceDim);
3670   double *pt=array->getPointer();
3671   const double *coo=getCoords()->getConstPointer();
3672   std::vector<int> conn;
3673   conn.reserve(2);
3674   for(int i=0;i<nbOfCells;i++)
3675     {
3676       conn.resize(0);
3677       getNodeIdsOfCell(i,conn);
3678       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3679     }
3680   ret->setArray(array);
3681   ret->setMesh(this);
3682   ret->synchronizeTimeWithSupport();
3683   return ret.retn();
3684 }
3685
3686 /*!
3687  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3688  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3689  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3690  * from. If a result face is shared by two 3D cells, then the face in included twice in
3691  * the result mesh.
3692  *  \param [in] origin - 3 components of a point defining location of the plane.
3693  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3694  *         must be greater than 1e-6.
3695  *  \param [in] eps - half-thickness of the plane.
3696  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3697  *         producing correspondent 2D cells. The caller is to delete this array
3698  *         using decrRef() as it is no more needed.
3699  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3700  *         not share the node coordinates array with \a this mesh. The caller is to
3701  *         delete this mesh using decrRef() as it is no more needed.  
3702  *  \throw If the coordinates array is not set.
3703  *  \throw If the nodal connectivity of cells is not defined.
3704  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3705  *  \throw If magnitude of \a vec is less than 1e-6.
3706  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3707  *  \throw If \a this includes quadratic cells.
3708  */
3709 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3710 {
3711   checkFullyDefined();
3712   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3714   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3715   if(candidates->empty())
3716     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3717   std::vector<int> nodes;
3718   DataArrayInt *cellIds1D=0;
3719   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3720   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3723   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3724   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3725   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3726   revDesc2=0; revDescIndx2=0;
3727   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3728   revDesc1=0; revDescIndx1=0;
3729   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3731   //
3732   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3733   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3734     cut3DCurve[*it]=-1;
3735   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3736   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3737   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3738                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3739                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3740   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3741   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3742   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3743   if(cellIds2->empty())
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3745   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3746   ret->setCoords(mDesc1->getCoords());
3747   ret->setConnectivity(conn,connI,true);
3748   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3749   return ret.retn();
3750 }
3751
3752 /*!
3753  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3754 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
3755 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3756 the result mesh.
3757  *  \param [in] origin - 3 components of a point defining location of the plane.
3758  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3759  *         must be greater than 1e-6.
3760  *  \param [in] eps - half-thickness of the plane.
3761  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3762  *         producing correspondent segments. The caller is to delete this array
3763  *         using decrRef() as it is no more needed.
3764  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3765  *         mesh in 3D space. This mesh does not share the node coordinates array with
3766  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3767  *         no more needed. 
3768  *  \throw If the coordinates array is not set.
3769  *  \throw If the nodal connectivity of cells is not defined.
3770  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3771  *  \throw If magnitude of \a vec is less than 1e-6.
3772  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3773  *  \throw If \a this includes quadratic cells.
3774  */
3775 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3776 {
3777   checkFullyDefined();
3778   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3781   if(candidates->empty())
3782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3783   std::vector<int> nodes;
3784   DataArrayInt *cellIds1D=0;
3785   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3786   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3789   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3791   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3792   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3794   //
3795   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3796   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3797     cut3DCurve[*it]=-1;
3798   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3799   int ncellsSub=subMesh->getNumberOfCells();
3800   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3801   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3802                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3803                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3804   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3805   conn->alloc(0,1);
3806   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3807   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3808   for(int i=0;i<ncellsSub;i++)
3809     {
3810       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3811         {
3812           if(cut3DSurf[i].first!=-2)
3813             {
3814               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3815               connI->pushBackSilent(conn->getNumberOfTuples());
3816               cellIds2->pushBackSilent(i);
3817             }
3818           else
3819             {
3820               int cellId3DSurf=cut3DSurf[i].second;
3821               int offset=nodalI[cellId3DSurf]+1;
3822               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3823               for(int j=0;j<nbOfEdges;j++)
3824                 {
3825                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3826                   connI->pushBackSilent(conn->getNumberOfTuples());
3827                   cellIds2->pushBackSilent(cellId3DSurf);
3828                 }
3829             }
3830         }
3831     }
3832   if(cellIds2->empty())
3833     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3834   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3835   ret->setCoords(mDesc1->getCoords());
3836   ret->setConnectivity(conn,connI,true);
3837   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3838   return ret.retn();
3839 }
3840
3841 /*!
3842  * Finds cells whose bounding boxes intersect a given plane.
3843  *  \param [in] origin - 3 components of a point defining location of the plane.
3844  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3845  *         must be greater than 1e-6.
3846  *  \param [in] eps - half-thickness of the plane.
3847  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3848  *         cells. The caller is to delete this array using decrRef() as it is no more
3849  *         needed.
3850  *  \throw If the coordinates array is not set.
3851  *  \throw If the nodal connectivity of cells is not defined.
3852  *  \throw If \a this->getSpaceDimension() != 3.
3853  *  \throw If magnitude of \a vec is less than 1e-6.
3854  *  \sa buildSlice3D()
3855  */
3856 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3857 {
3858   checkFullyDefined();
3859   if(getSpaceDimension()!=3)
3860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3861   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3862   if(normm<1e-6)
3863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3864   double vec2[3];
3865   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3866   double angle=acos(vec[2]/normm);
3867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3868   double bbox[6];
3869   if(angle>eps)
3870     {
3871       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3872       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3873       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3874       mw->setCoords(coo);
3875       mw->getBoundingBox(bbox);
3876       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3877       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3878     }
3879   else
3880     {
3881       getBoundingBox(bbox);
3882       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3883       cellIds=getCellsInBoundingBox(bbox,eps);
3884     }
3885   return cellIds.retn();
3886 }
3887
3888 /*!
3889  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3890  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3891  * No consideration of coordinate is done by this method.
3892  * 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)
3893  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3894  */
3895 bool MEDCouplingUMesh::isContiguous1D() const
3896 {
3897   if(getMeshDimension()!=1)
3898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3899   int nbCells=getNumberOfCells();
3900   if(nbCells<1)
3901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3902   const int *connI=_nodal_connec_index->getConstPointer();
3903   const int *conn=_nodal_connec->getConstPointer();
3904   int ref=conn[connI[0]+2];
3905   for(int i=1;i<nbCells;i++)
3906     {
3907       if(conn[connI[i]+1]!=ref)
3908         return false;
3909       ref=conn[connI[i]+2];
3910     }
3911   return true;
3912 }
3913
3914 /*!
3915  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3916  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3917  * \param pt reference point of the line
3918  * \param v normalized director vector of the line
3919  * \param eps max precision before throwing an exception
3920  * \param res output of size this->getNumberOfCells
3921  */
3922 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3923 {
3924   if(getMeshDimension()!=1)
3925     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3926   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3927     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3928   if(getSpaceDimension()!=3)
3929     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3930   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3931   const double *fPtr=f->getArray()->getConstPointer();
3932   double tmp[3];
3933   for(int i=0;i<getNumberOfCells();i++)
3934     {
3935       const double *tmp1=fPtr+3*i;
3936       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3937       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3938       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3939       double n1=INTERP_KERNEL::norm<3>(tmp);
3940       n1/=INTERP_KERNEL::norm<3>(tmp1);
3941       if(n1>eps)
3942         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3943     }
3944   const double *coo=getCoords()->getConstPointer();
3945   for(int i=0;i<getNumberOfNodes();i++)
3946     {
3947       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3948       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3949       res[i]=std::accumulate(tmp,tmp+3,0.);
3950     }
3951 }
3952
3953 /*!
3954  * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. 
3955  * \a this is expected to be a mesh so that its space dimension is equal to its
3956  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3957  * 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).
3958  *
3959  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3960  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3961  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3962  *
3963  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3964  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3965  *
3966  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3967  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3968  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3969  * \return the positive value of the distance.
3970  * \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
3971  * dimension - 1.
3972  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3973  */
3974 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3975 {
3976   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3977   if(meshDim!=spaceDim-1)
3978     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3979   if(meshDim!=2 && meshDim!=1)
3980     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3981   checkFullyDefined();
3982   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3983     { 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()); }
3984   DataArrayInt *ret1=0;
3985   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3986   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3988   cellId=*ret1Safe->begin();
3989   return *ret0->begin();
3990 }
3991
3992 /*!
3993  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3994  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3995  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3996  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3997  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3998  * 
3999  * \a this is expected to be a mesh so that its space dimension is equal to its
4000  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4001  * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4002  *
4003  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4004  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4005  *
4006  * \param [in] pts the list of points in which each tuple represents a point
4007  * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
4008  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4009  * \throw if number of components of \a pts is not equal to the space dimension.
4010  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4011  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4012  */
4013 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4014 {
4015   if(!pts)
4016     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4017   pts->checkAllocated();
4018   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4019   if(meshDim!=spaceDim-1)
4020     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4021   if(meshDim!=2 && meshDim!=1)
4022     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4023   if(pts->getNumberOfComponents()!=spaceDim)
4024     {
4025       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4026       throw INTERP_KERNEL::Exception(oss.str().c_str());
4027     }
4028   checkFullyDefined();
4029   int nbCells=getNumberOfCells();
4030   if(nbCells==0)
4031     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4032   int nbOfPts=pts->getNumberOfTuples();
4033   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4035   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4036   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4037   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4038   const double *bbox(bboxArr->begin());
4039   switch(spaceDim)
4040   {
4041     case 3:
4042       {
4043         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4044         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4045           {
4046             double x=std::numeric_limits<double>::max();
4047             std::vector<int> elems;
4048             myTree.getMinDistanceOfMax(ptsPtr,x);
4049             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4050             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4051           }
4052         break;
4053       }
4054     case 2:
4055       {
4056         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4057         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4058           {
4059             double x=std::numeric_limits<double>::max();
4060             std::vector<int> elems;
4061             myTree.getMinDistanceOfMax(ptsPtr,x);
4062             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4063             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4064           }
4065         break;
4066       }
4067     default:
4068       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4069   }
4070   cellIds=ret1.retn();
4071   return ret0.retn();
4072 }
4073
4074 /*!
4075  * \param [in] pt the start pointer (included) of the coordinates of the point
4076  * \param [in] cellIdsBg the start pointer (included) of cellIds
4077  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4078  * \param [in] nc nodal connectivity
4079  * \param [in] ncI nodal connectivity index
4080  * \param [in,out] ret0 the min distance between \a this and the external input point
4081  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4082  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4083  */
4084 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4085 {
4086   cellId=-1;
4087   ret0=std::numeric_limits<double>::max();
4088   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4089     {
4090       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4091       {
4092         case INTERP_KERNEL::NORM_TRI3:
4093           {
4094             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4095             if(tmp<ret0)
4096               { ret0=tmp; cellId=*zeCell; }
4097             break;
4098           }
4099         case INTERP_KERNEL::NORM_QUAD4:
4100         case INTERP_KERNEL::NORM_POLYGON:
4101           {
4102             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4103             if(tmp<ret0)
4104               { ret0=tmp; cellId=*zeCell; }
4105             break;
4106           }
4107         default:
4108           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4109       }
4110     }
4111 }
4112
4113 /*!
4114  * \param [in] pt the start pointer (included) of the coordinates of the point
4115  * \param [in] cellIdsBg the start pointer (included) of cellIds
4116  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4117  * \param [in] nc nodal connectivity
4118  * \param [in] ncI nodal connectivity index
4119  * \param [in,out] ret0 the min distance between \a this and the external input point
4120  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4121  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4122  */
4123 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4124 {
4125   cellId=-1;
4126   ret0=std::numeric_limits<double>::max();
4127   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4128     {
4129       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4130       {
4131         case INTERP_KERNEL::NORM_SEG2:
4132           {
4133             std::size_t uselessEntry=0;
4134             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4135             tmp=sqrt(tmp);
4136             if(tmp<ret0)
4137               { ret0=tmp; cellId=*zeCell; }
4138             break;
4139           }
4140         default:
4141           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4142       }
4143     }
4144 }
4145
4146 /*!
4147  * Finds cells in contact with a ball (i.e. a point with precision). 
4148  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4149  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4150  *
4151  * \warning This method is suitable if the caller intends to evaluate only one
4152  *          point, for more points getCellsContainingPoints() is recommended as it is
4153  *          faster. 
4154  *  \param [in] pos - array of coordinates of the ball central point.
4155  *  \param [in] eps - ball radius.
4156  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4157  *         if there are no such cells.
4158  *  \throw If the coordinates array is not set.
4159  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4160  */
4161 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4162 {
4163   std::vector<int> elts;
4164   getCellsContainingPoint(pos,eps,elts);
4165   if(elts.empty())
4166     return -1;
4167   return elts.front();
4168 }
4169
4170 /*!
4171  * Finds cells in contact with a ball (i.e. a point with precision).
4172  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4173  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4174  * \warning This method is suitable if the caller intends to evaluate only one
4175  *          point, for more points getCellsContainingPoints() is recommended as it is
4176  *          faster. 
4177  *  \param [in] pos - array of coordinates of the ball central point.
4178  *  \param [in] eps - ball radius.
4179  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4180  *         before inserting ids.
4181  *  \throw If the coordinates array is not set.
4182  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4183  *
4184  *  \if ENABLE_EXAMPLES
4185  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4186  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4187  *  \endif
4188  */
4189 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4190 {
4191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4192   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4193   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4194 }
4195
4196 /// @cond INTERNAL
4197
4198 namespace ParaMEDMEM
4199 {
4200   template<const int SPACEDIMM>
4201   class DummyClsMCUG
4202   {
4203   public:
4204     static const int MY_SPACEDIM=SPACEDIMM;
4205     static const int MY_MESHDIM=8;
4206     typedef int MyConnType;
4207     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4208     // begin
4209     // useless, but for windows compilation ...
4210     const double* getCoordinatesPtr() const { return 0; }
4211     const int* getConnectivityPtr() const { return 0; }
4212     const int* getConnectivityIndexPtr() const { return 0; }
4213     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4214     // end
4215   };
4216
4217
4218
4219   /*!
4220    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4221    */
4222   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4223   {
4224     INTERP_KERNEL::Edge *ret(0);
4225     MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4226     m[n0]=bg[0]; m[n1]=bg[1];
4227     switch(typ)
4228     {
4229       case INTERP_KERNEL::NORM_SEG2:
4230         {
4231           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4232           break;
4233         }
4234       case INTERP_KERNEL::NORM_SEG3:
4235         {
4236           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4237           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4238           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4239           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4240           bool colinearity(inters.areColinears());
4241           delete e1; delete e2;
4242           if(colinearity)
4243             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4244           else
4245             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4246           break;
4247         }
4248       default:
4249         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4250     }
4251     return ret;
4252   }
4253
4254   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4255   {
4256     INTERP_KERNEL::Edge *ret=0;
4257     switch(typ)
4258     {
4259       case INTERP_KERNEL::NORM_SEG2:
4260         {
4261           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4262           break;
4263         }
4264       case INTERP_KERNEL::NORM_SEG3:
4265         {
4266           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4267           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4268           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4269           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4270           bool colinearity=inters.areColinears();
4271           delete e1; delete e2;
4272           if(colinearity)
4273             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4274           else
4275             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4276           mapp2[bg[2]].second=false;
4277           break;
4278         }
4279       default:
4280         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4281     }
4282     return ret;
4283   }
4284
4285   /*!
4286    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4287    * the global mesh 'mDesc'.
4288    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4289    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4290    */
4291   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4292                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4293   {
4294     mapp.clear();
4295     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.
4296     const double *coo=mDesc->getCoords()->getConstPointer();
4297     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4298     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4299     std::set<int> s;
4300     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4301       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4302     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4303       {
4304         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4305         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4306       }
4307     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4308     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4309       {
4310         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4311         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4312       }
4313     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4314       {
4315         if((*it2).second.second)
4316           mapp[(*it2).second.first]=(*it2).first;
4317         ((*it2).second.first)->decrRef();
4318       }
4319     return ret;
4320   }
4321
4322   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4323   {
4324     if(nodeId>=offset2)
4325       {
4326         int locId=nodeId-offset2;
4327         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4328       }
4329     if(nodeId>=offset1)
4330       {
4331         int locId=nodeId-offset1;
4332         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4333       }
4334     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4335   }
4336
4337   /**
4338    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4339    */
4340   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4341                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4342                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4343   {
4344     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4345       {
4346         int eltId1=abs(*desc1)-1;
4347         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4348           {
4349             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4350             if(it==mappRev.end())
4351               {
4352                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4353                 mapp[node]=*it1;
4354                 mappRev[*it1]=node;
4355               }
4356           }
4357       }
4358   }
4359 }
4360
4361 /// @endcond
4362
4363 template<int SPACEDIM>
4364 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4365                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4366 {
4367   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4368   int *eltsIndexPtr(eltsIndex->getPointer());
4369   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4370   const double *bbox(bboxArr->begin());
4371   int nbOfCells=getNumberOfCells();
4372   const int *conn=_nodal_connec->getConstPointer();
4373   const int *connI=_nodal_connec_index->getConstPointer();
4374   double bb[2*SPACEDIM];
4375   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4376   for(int i=0;i<nbOfPoints;i++)
4377     {
4378       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4379       for(int j=0;j<SPACEDIM;j++)
4380         {
4381           bb[2*j]=pos[SPACEDIM*i+j];
4382           bb[2*j+1]=pos[SPACEDIM*i+j];
4383         }
4384       std::vector<int> candidates;
4385       myTree.getIntersectingElems(bb,candidates);
4386       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4387         {
4388           int sz(connI[(*iter)+1]-connI[*iter]-1);
4389           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4390           bool status(false);
4391           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4392             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4393           else
4394             {
4395               if(SPACEDIM!=2)
4396                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4397               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4398               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4399               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4400               INTERP_KERNEL::QuadraticPolygon *pol(0);
4401               for(int j=0;j<sz;j++)
4402                 {
4403                   int nodeId(conn[connI[*iter]+1+j]);
4404                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4405                 }
4406               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4407                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4408               else
4409                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4410               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4411               double a(0.),b(0.),c(0.);
4412               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4413               status=pol->isInOrOut2(n);
4414               delete pol; n->decrRef();
4415             }
4416           if(status)
4417             {
4418               eltsIndexPtr[i+1]++;
4419               elts->pushBackSilent(*iter);
4420             }
4421         }
4422     }
4423 }
4424 /*!
4425  * Finds cells in contact with several balls (i.e. points with precision).
4426  * This method is an extension of getCellContainingPoint() and
4427  * getCellsContainingPoint() for the case of multiple points.
4428  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4429  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4430  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4431  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4432  *         this->getSpaceDimension() * \a nbOfPoints 
4433  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4434  *  \param [in] eps - radius of balls (i.e. the precision).
4435  *  \param [out] elts - vector returning ids of found cells.
4436  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4437  *         dividing cell ids in \a elts into groups each referring to one
4438  *         point. Its every element (except the last one) is an index pointing to the
4439  *         first id of a group of cells. For example cells in contact with the *i*-th
4440  *         point are described by following range of indices:
4441  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4442  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4443  *         Number of cells in contact with the *i*-th point is
4444  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4445  *  \throw If the coordinates array is not set.
4446  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4447  *
4448  *  \if ENABLE_EXAMPLES
4449  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4450  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4451  *  \endif
4452  */
4453 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4454                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4455 {
4456   int spaceDim=getSpaceDimension();
4457   int mDim=getMeshDimension();
4458   if(spaceDim==3)
4459     {
4460       if(mDim==3)
4461         {
4462           const double *coords=_coords->getConstPointer();
4463           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4464         }
4465       /*else if(mDim==2)
4466         {
4467
4468         }*/
4469       else
4470         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4471     }
4472   else if(spaceDim==2)
4473     {
4474       if(mDim==2)
4475         {
4476           const double *coords=_coords->getConstPointer();
4477           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4478         }
4479       else
4480         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4481     }
4482   else if(spaceDim==1)
4483     {
4484       if(mDim==1)
4485         {
4486           const double *coords=_coords->getConstPointer();
4487           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4488         }
4489       else
4490         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4491     }
4492   else
4493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4494 }
4495
4496 /*!
4497  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4498  * least two its edges intersect each other anywhere except their extremities. An
4499  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4500  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4501  *         cleared before filling in.
4502  *  \param [in] eps - precision.
4503  *  \throw If \a this->getMeshDimension() != 2.
4504  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4505  */
4506 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4507 {
4508   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4509   if(getMeshDimension()!=2)
4510     throw INTERP_KERNEL::Exception(msg);
4511   int spaceDim=getSpaceDimension();
4512   if(spaceDim!=2 && spaceDim!=3)
4513     throw INTERP_KERNEL::Exception(msg);
4514   const int *conn=_nodal_connec->getConstPointer();
4515   const int *connI=_nodal_connec_index->getConstPointer();
4516   int nbOfCells=getNumberOfCells();
4517   std::vector<double> cell2DinS2;
4518   for(int i=0;i<nbOfCells;i++)
4519     {
4520       int offset=connI[i];
4521       int nbOfNodesForCell=connI[i+1]-offset-1;
4522       if(nbOfNodesForCell<=3)
4523         continue;
4524       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4525       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4526       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4527         cells.push_back(i);
4528       cell2DinS2.clear();
4529     }
4530 }
4531
4532 /*!
4533  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4534  *
4535  * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4536  * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4537  * 
4538  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4539  * This convex envelop is computed using Jarvis march algorithm.
4540  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4541  * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4542  * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4543  *
4544  * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4545  * \sa MEDCouplingUMesh::colinearize2D
4546  */
4547 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4548 {
4549   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4550     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4551   checkFullyDefined();
4552   const double *coords=getCoords()->getConstPointer();
4553   int nbOfCells=getNumberOfCells();
4554   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4555   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4557   int *workIndexOut=nodalConnecIndexOut->getPointer();
4558   *workIndexOut=0;
4559   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4560   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4561   std::set<INTERP_KERNEL::NormalizedCellType> types;
4562   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4563   isChanged->alloc(0,1);
4564   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4565     {
4566       int pos=nodalConnecOut->getNumberOfTuples();
4567       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4568         isChanged->pushBackSilent(i);
4569       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4570       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4571     }
4572   if(isChanged->empty())
4573     return 0;
4574   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4575   _types=types;
4576   return isChanged.retn();
4577 }
4578
4579 /*!
4580  * This method is \b NOT const because it can modify \a this.
4581  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4582  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4583  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4584  * \b 1 for translation and rotation around point of 'mesh1D'.
4585  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4586  */
4587 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4588 {
4589   checkFullyDefined();
4590   mesh1D->checkFullyDefined();
4591   if(!mesh1D->isContiguous1D())
4592     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4593   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4594     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4595   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4596     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4597   if(mesh1D->getMeshDimension()!=1)
4598     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4599   bool isQuad=false;
4600   if(isPresenceOfQuadratic())
4601     {
4602       if(mesh1D->isFullyQuadratic())
4603         isQuad=true;
4604       else
4605         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4606     }
4607   zipCoords();
4608   int oldNbOfNodes=getNumberOfNodes();
4609   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4610   switch(policy)
4611   {
4612     case 0:
4613       {
4614         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4615         break;
4616       }
4617     case 1:
4618       {
4619         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4620         break;
4621       }
4622     default:
4623       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4624   }
4625   setCoords(newCoords);
4626   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4627   updateTime();
4628   return ret.retn();
4629 }
4630
4631 /*!
4632  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4633  * If it is not the case an exception will be thrown.
4634  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4635  * intersection of plane defined by ('origin','vec').
4636  * This method has one in/out parameter : 'cut3DCurve'.
4637  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4638  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4639  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4640  * This method will throw an exception if \a this contains a non linear segment.
4641  */
4642 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4643 {
4644   checkFullyDefined();
4645   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4646     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4647   int ncells=getNumberOfCells();
4648   int nnodes=getNumberOfNodes();
4649   double vec2[3],vec3[3],vec4[3];
4650   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4651   if(normm<1e-6)
4652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4653   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4654   const int *conn=_nodal_connec->getConstPointer();
4655   const int *connI=_nodal_connec_index->getConstPointer();
4656   const double *coo=_coords->getConstPointer();
4657   std::vector<double> addCoo;
4658   for(int i=0;i<ncells;i++)
4659     {
4660       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4661         {
4662           if(cut3DCurve[i]==-2)
4663             {
4664               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4665               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];
4666               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4667               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4668               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4669                 {
4670                   const double *st2=coo+3*st;
4671                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4672                   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]));
4673                   if(pos>eps && pos<1-eps)
4674                     {
4675                       int nNode=((int)addCoo.size())/3;
4676                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4677                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4678                       cut3DCurve[i]=nnodes+nNode;
4679                     }
4680                 }
4681             }
4682         }
4683       else
4684         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4685     }
4686   if(!addCoo.empty())
4687     {
4688       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4689       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4690       coo2->alloc(newNbOfNodes,3);
4691       double *tmp=coo2->getPointer();
4692       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4693       std::copy(addCoo.begin(),addCoo.end(),tmp);
4694       DataArrayDouble::SetArrayIn(coo2,_coords);
4695     }
4696 }
4697
4698 /*!
4699  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4700  * \param mesh1D is the input 1D mesh used for translation computation.
4701  * \return newCoords new coords filled by this method. 
4702  */
4703 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4704 {
4705   int oldNbOfNodes=getNumberOfNodes();
4706   int nbOf1DCells=mesh1D->getNumberOfCells();
4707   int spaceDim=getSpaceDimension();
4708   DataArrayDouble *ret=DataArrayDouble::New();
4709   std::vector<bool> isQuads;
4710   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4711   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4712   double *retPtr=ret->getPointer();
4713   const double *coords=getCoords()->getConstPointer();
4714   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4715   std::vector<int> v;
4716   std::vector<double> c;
4717   double vec[3];
4718   v.reserve(3);
4719   c.reserve(6);
4720   for(int i=0;i<nbOf1DCells;i++)
4721     {
4722       v.resize(0);
4723       mesh1D->getNodeIdsOfCell(i,v);
4724       c.resize(0);
4725       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4726       mesh1D->getCoordinatesOfNode(v[0],c);
4727       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4728       for(int j=0;j<oldNbOfNodes;j++)
4729         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4730       if(isQuad)
4731         {
4732           c.resize(0);
4733           mesh1D->getCoordinatesOfNode(v[1],c);
4734           mesh1D->getCoordinatesOfNode(v[0],c);
4735           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4736           for(int j=0;j<oldNbOfNodes;j++)
4737             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4738         }
4739     }
4740   ret->copyStringInfoFrom(*getCoords());
4741   return ret;
4742 }
4743
4744 /*!
4745  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4746  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4747  * \return newCoords new coords filled by this method. 
4748  */
4749 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4750 {
4751   if(mesh1D->getSpaceDimension()==2)
4752     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4753   if(mesh1D->getSpaceDimension()==3)
4754     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4755   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4756 }
4757
4758 /*!
4759  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4760  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4761  * \return newCoords new coords filled by this method. 
4762  */
4763 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4764 {
4765   if(isQuad)
4766     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4767   int oldNbOfNodes=getNumberOfNodes();
4768   int nbOf1DCells=mesh1D->getNumberOfCells();
4769   if(nbOf1DCells<2)
4770     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4771   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4772   int nbOfLevsInVec=nbOf1DCells+1;
4773   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4774   double *retPtr=ret->getPointer();
4775   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4776   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4777   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4778   tmp->setCoords(tmp2);
4779   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4780   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4781   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4782   for(int i=1;i<nbOfLevsInVec;i++)
4783     {
4784       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4785       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4786       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4787       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4788       tmp->translate(vec);
4789       double tmp3[2],radius,alpha,alpha0;
4790       const double *p0=i+1<nbOfLevsInVec?begin:third;
4791       const double *p1=i+1<nbOfLevsInVec?end:begin;
4792       const double *p2=i+1<nbOfLevsInVec?third:end;
4793       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4794       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]);
4795       double angle=acos(cosangle/(radius*radius));
4796       tmp->rotate(end,0,angle);
4797       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4798     }
4799   return ret.retn();
4800 }
4801
4802 /*!
4803  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4804  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4805  * \return newCoords new coords filled by this method. 
4806  */
4807 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4808 {
4809   if(isQuad)
4810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4811   int oldNbOfNodes=getNumberOfNodes();
4812   int nbOf1DCells=mesh1D->getNumberOfCells();
4813   if(nbOf1DCells<2)
4814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4815   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4816   int nbOfLevsInVec=nbOf1DCells+1;
4817   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4818   double *retPtr=ret->getPointer();
4819   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4820   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4821   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4822   tmp->setCoords(tmp2);
4823   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4824   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4825   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4826   for(int i=1;i<nbOfLevsInVec;i++)
4827     {
4828       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4829       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4830       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4831       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4832       tmp->translate(vec);
4833       double tmp3[2],radius,alpha,alpha0;
4834       const double *p0=i+1<nbOfLevsInVec?begin:third;
4835       const double *p1=i+1<nbOfLevsInVec?end:begin;
4836       const double *p2=i+1<nbOfLevsInVec?third:end;
4837       double vecPlane[3]={
4838         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4839         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4840         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4841       };
4842       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4843       if(norm>1.e-7)
4844         {
4845           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4846           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4847           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4848           double s2=norm2;
4849           double c2=cos(asin(s2));
4850           double m[3][3]={
4851             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4852             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4853             {-vec2[1]*s2, vec2[0]*s2, c2}
4854           };
4855           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]};
4856           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]};
4857           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]};
4858           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4859           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]);
4860           double angle=acos(cosangle/(radius*radius));
4861           tmp->rotate(end,vecPlane,angle);
4862         }
4863       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4864     }
4865   return ret.retn();
4866 }
4867
4868 /*!
4869  * This method is private because not easy to use for end user. This method is const contrary to
4870  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4871  * the coords sorted slice by slice.
4872  * \param isQuad specifies presence of quadratic cells.
4873  */
4874 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4875 {
4876   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4877   int nbOf2DCells=getNumberOfCells();
4878   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4879   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4880   const int *conn=_nodal_connec->getConstPointer();
4881   const int *connI=_nodal_connec_index->getConstPointer();
4882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4884   newConnI->alloc(nbOf3DCells+1,1);
4885   int *newConnIPtr=newConnI->getPointer();
4886   *newConnIPtr++=0;
4887   std::vector<int> newc;
4888   for(int j=0;j<nbOf2DCells;j++)
4889     {
4890       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4891       *newConnIPtr++=(int)newc.size();
4892     }
4893   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4894   int *newConnPtr=newConn->getPointer();
4895   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4896   newConnIPtr=newConnI->getPointer();
4897   for(int iz=0;iz<nbOf1DCells;iz++)
4898     {
4899       if(iz!=0)
4900         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4901       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4902         {
4903           int icell=(int)(iter-newc.begin());
4904           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4905             {
4906               if(*iter!=-1)
4907                 *newConnPtr=(*iter)+iz*deltaPerLev;
4908               else
4909                 *newConnPtr=-1;
4910             }
4911           else
4912             *newConnPtr=(*iter);
4913         }
4914     }
4915   ret->setConnectivity(newConn,newConnI,true);
4916   ret->setCoords(getCoords());
4917   return ret;
4918 }
4919
4920 /*!
4921  * Checks if \a this mesh is constituted by only quadratic cells.
4922  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4923  *  \throw If the coordinates array is not set.
4924  *  \throw If the nodal connectivity of cells is not defined.
4925  */
4926 bool MEDCouplingUMesh::isFullyQuadratic() const
4927 {
4928   checkFullyDefined();
4929   bool ret=true;
4930   int nbOfCells=getNumberOfCells();
4931   for(int i=0;i<nbOfCells && ret;i++)
4932     {
4933       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4934       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4935       ret=cm.isQuadratic();
4936     }
4937   return ret;
4938 }
4939
4940 /*!
4941  * Checks if \a this mesh includes any quadratic cell.
4942  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4943  *  \throw If the coordinates array is not set.
4944  *  \throw If the nodal connectivity of cells is not defined.
4945  */
4946 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4947 {
4948   checkFullyDefined();
4949   bool ret=false;
4950   int nbOfCells=getNumberOfCells();
4951   for(int i=0;i<nbOfCells && !ret;i++)
4952     {
4953       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4954       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4955       ret=cm.isQuadratic();
4956     }
4957   return ret;
4958 }
4959
4960 /*!
4961  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4962  * this mesh, it remains unchanged.
4963  *  \throw If the coordinates array is not set.
4964  *  \throw If the nodal connectivity of cells is not defined.
4965  */
4966 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4967 {
4968   checkFullyDefined();
4969   int nbOfCells=getNumberOfCells();
4970   int delta=0;
4971   const int *iciptr=_nodal_connec_index->getConstPointer();
4972   for(int i=0;i<nbOfCells;i++)
4973     {
4974       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4975       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4976       if(cm.isQuadratic())
4977         {
4978           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4979           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4980           if(!cml.isDynamic())
4981             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4982           else
4983             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4984         }
4985     }
4986   if(delta==0)
4987     return ;
4988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4990   const int *icptr=_nodal_connec->getConstPointer();
4991   newConn->alloc(getMeshLength()-delta,1);
4992   newConnI->alloc(nbOfCells+1,1);
4993   int *ocptr=newConn->getPointer();
4994   int *ociptr=newConnI->getPointer();
4995   *ociptr=0;
4996   _types.clear();
4997   for(int i=0;i<nbOfCells;i++,ociptr++)
4998     {
4999       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5000       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5001       if(!cm.isQuadratic())
5002         {
5003           _types.insert(type);
5004           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5005           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5006         }
5007       else
5008         {
5009           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5010           _types.insert(typel);
5011           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5012           int newNbOfNodes=cml.getNumberOfNodes();
5013           if(cml.isDynamic())
5014             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5015           *ocptr++=(int)typel;
5016           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5017           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5018         }
5019     }
5020   setConnectivity(newConn,newConnI,false);
5021 }
5022
5023 /*!
5024  * This method converts all linear cell in \a this to quadratic one.
5025  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5026  * 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)
5027  * 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.
5028  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5029  * end of the existing coordinates.
5030  * 
5031  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5032  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5033  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5034  * 
5035  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5036  *
5037  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5038  */
5039 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5040 {
5041   DataArrayInt *conn=0,*connI=0;
5042   DataArrayDouble *coords=0;
5043   std::set<INTERP_KERNEL::NormalizedCellType> types;
5044   checkFullyDefined();
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5046   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5047   int meshDim=getMeshDimension();
5048   switch(conversionType)
5049   {
5050     case 0:
5051       switch(meshDim)
5052       {
5053         case 1:
5054           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5055           connSafe=conn; connISafe=connI; coordsSafe=coords;
5056           break;
5057         case 2:
5058           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5059           connSafe=conn; connISafe=connI; coordsSafe=coords;
5060           break;
5061         case 3:
5062           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5063           connSafe=conn; connISafe=connI; coordsSafe=coords;
5064           break;
5065         default:
5066           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5067       }
5068       break;
5069         case 1:
5070           {
5071             switch(meshDim)
5072             {
5073               case 1:
5074                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5075                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5076                 break;
5077               case 2:
5078                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5079                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5080                 break;
5081               case 3:
5082                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5083                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5084                 break;
5085               default:
5086                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5087             }
5088             break;
5089           }
5090         default:
5091           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5092   }
5093   setConnectivity(connSafe,connISafe,false);
5094   _types=types;
5095   setCoords(coordsSafe);
5096   return ret.retn();
5097 }
5098
5099 #if 0
5100 /*!
5101  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5102  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5103  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5104  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5105  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5106  * This method can be seen as the opposite method of colinearize2D.
5107  * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5108  * to avoid to modify the numbering of existing nodes.
5109  *
5110  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5111  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5112  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5113  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5114  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5115  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5116  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5117  *
5118  * \sa buildDescendingConnectivity2
5119  */
5120 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5121                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5122 {
5123   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5124     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5125   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5126   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5127     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5128   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5129     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5130   //DataArrayInt *out0(0),*outi0(0);
5131   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5132   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5133   //out0s=out0s->buildUnique(); out0s->sort(true);
5134 }
5135 #endif
5136
5137 /*!
5138  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5139  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5140  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5141  */
5142 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5143 {
5144   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5148   int nbOfCells=getNumberOfCells();
5149   int nbOfNodes=getNumberOfNodes();
5150   const int *cPtr=_nodal_connec->getConstPointer();
5151   const int *icPtr=_nodal_connec_index->getConstPointer();
5152   int lastVal=0,offset=nbOfNodes;
5153   for(int i=0;i<nbOfCells;i++,icPtr++)
5154     {
5155       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5156       if(type==INTERP_KERNEL::NORM_SEG2)
5157         {
5158           types.insert(INTERP_KERNEL::NORM_SEG3);
5159           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5160           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5161           newConn->pushBackSilent(offset++);
5162           lastVal+=4;
5163           newConnI->pushBackSilent(lastVal);
5164           ret->pushBackSilent(i);
5165         }
5166       else
5167         {
5168           types.insert(type);
5169           lastVal+=(icPtr[1]-icPtr[0]);
5170           newConnI->pushBackSilent(lastVal);
5171           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5172         }
5173     }
5174   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5175   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5176   return ret.retn();
5177 }
5178
5179 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
5180 {
5181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5184   //
5185   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5186   DataArrayInt *conn1D=0,*conn1DI=0;
5187   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5188   DataArrayDouble *coordsTmp=0;
5189   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5190   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5192   const int *c1DPtr=conn1D->begin();
5193   const int *c1DIPtr=conn1DI->begin();
5194   int nbOfCells=getNumberOfCells();
5195   const int *cPtr=_nodal_connec->getConstPointer();
5196   const int *icPtr=_nodal_connec_index->getConstPointer();
5197   int lastVal=0;
5198   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5199     {
5200       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5201       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5202       if(!cm.isQuadratic())
5203         {
5204           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5205           types.insert(typ2); newConn->pushBackSilent(typ2);
5206           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5207           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5208             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5209           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5210           newConnI->pushBackSilent(lastVal);
5211           ret->pushBackSilent(i);
5212         }
5213       else
5214         {
5215           types.insert(typ);
5216           lastVal+=(icPtr[1]-icPtr[0]);
5217           newConnI->pushBackSilent(lastVal);
5218           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5219         }
5220     }
5221   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5222   return ret.retn();
5223 }
5224
5225 /*!
5226  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5227  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5228  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5229  */
5230 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5231 {
5232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5233   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5234   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5235 }
5236
5237 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5238 {
5239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5240   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5241   //
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5245   //
5246   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5247   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5248   DataArrayInt *conn1D=0,*conn1DI=0;
5249   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5250   DataArrayDouble *coordsTmp=0;
5251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5252   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5254   const int *c1DPtr=conn1D->begin();
5255   const int *c1DIPtr=conn1DI->begin();
5256   int nbOfCells=getNumberOfCells();
5257   const int *cPtr=_nodal_connec->getConstPointer();
5258   const int *icPtr=_nodal_connec_index->getConstPointer();
5259   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5260   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5261     {
5262       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5263       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5264       if(!cm.isQuadratic())
5265         {
5266           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5267           types.insert(typ2); newConn->pushBackSilent(typ2);
5268           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5269           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5270             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5271           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5272           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5273           newConnI->pushBackSilent(lastVal);
5274           ret->pushBackSilent(i);
5275         }
5276       else
5277         {
5278           types.insert(typ);
5279           lastVal+=(icPtr[1]-icPtr[0]);
5280           newConnI->pushBackSilent(lastVal);
5281           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5282         }
5283     }
5284   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5285   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5286   return ret.retn();
5287 }
5288
5289 /*!
5290  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5291  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5292  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5293  */
5294 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5295 {
5296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5298   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5299 }
5300
5301 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5302 {
5303   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5304   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5306   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5307   //
5308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5311   //
5312   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5313   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5314   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5315   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5316   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5321   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5323   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5324   int nbOfCells=getNumberOfCells();
5325   const int *cPtr=_nodal_connec->getConstPointer();
5326   const int *icPtr=_nodal_connec_index->getConstPointer();
5327   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5328   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5329     {
5330       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5331       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5332       if(!cm.isQuadratic())
5333         {
5334           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5335           if(typ2==INTERP_KERNEL::NORM_ERROR)
5336             {
5337               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5338               throw INTERP_KERNEL::Exception(oss.str().c_str());
5339             }
5340           types.insert(typ2); newConn->pushBackSilent(typ2);
5341           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5342           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5343             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5344           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5345             {
5346               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5347               int tmpPos=newConn->getNumberOfTuples();
5348               newConn->pushBackSilent(nodeId2);
5349               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5350             }
5351           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5352           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5353           newConnI->pushBackSilent(lastVal);
5354           ret->pushBackSilent(i);
5355         }
5356       else
5357         {
5358           types.insert(typ);
5359           lastVal+=(icPtr[1]-icPtr[0]);
5360           newConnI->pushBackSilent(lastVal);
5361           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5362         }
5363     }
5364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5366   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5367   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5368   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5369   int *c=newConn->getPointer();
5370   const int *cI(newConnI->begin());
5371   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5372     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5373   offset=coordsTmp2Safe->getNumberOfTuples();
5374   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5375     c[cI[(*elt)+1]-1]+=offset;
5376   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5377   return ret.retn();
5378 }
5379
5380 /*!
5381  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5382  * so that the number of cells remains the same. Quadratic faces are converted to
5383  * polygons. This method works only for 2D meshes in
5384  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5385  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5386  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5387  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5388  *         a polylinized edge constituting the input polygon.
5389  *  \throw If the coordinates array is not set.
5390  *  \throw If the nodal connectivity of cells is not defined.
5391  *  \throw If \a this->getMeshDimension() != 2.
5392  *  \throw If \a this->getSpaceDimension() != 2.
5393  */
5394 void MEDCouplingUMesh::tessellate2D(double eps)
5395 {
5396   checkFullyDefined();
5397   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5398     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5399   double epsa=fabs(eps);
5400   if(epsa<std::numeric_limits<double>::min())
5401     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 !");
5402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5406   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5407   revDesc1=0; revDescIndx1=0;
5408   mDesc->tessellate2DCurve(eps);
5409   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5410   setCoords(mDesc->getCoords());
5411 }
5412
5413 /*!
5414  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5415  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5416  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5417  *         a sub-divided edge.
5418  *  \throw If the coordinates array is not set.
5419  *  \throw If the nodal connectivity of cells is not defined.
5420  *  \throw If \a this->getMeshDimension() != 1.
5421  *  \throw If \a this->getSpaceDimension() != 2.
5422  */
5423 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5424 {
5425   checkFullyDefined();
5426   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5428   double epsa=fabs(eps);
5429   if(epsa<std::numeric_limits<double>::min())
5430     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 !");
5431   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5432   int nbCells=getNumberOfCells();
5433   int nbNodes=getNumberOfNodes();
5434   const int *conn=_nodal_connec->getConstPointer();
5435   const int *connI=_nodal_connec_index->getConstPointer();
5436   const double *coords=_coords->getConstPointer();
5437   std::vector<double> addCoo;
5438   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5440   newConnI->alloc(nbCells+1,1);
5441   int *newConnIPtr=newConnI->getPointer();
5442   *newConnIPtr=0;
5443   int tmp1[3];
5444   INTERP_KERNEL::Node *tmp2[3];
5445   std::set<INTERP_KERNEL::NormalizedCellType> types;
5446   for(int i=0;i<nbCells;i++,newConnIPtr++)
5447     {
5448       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5449       if(cm.isQuadratic())
5450         {//assert(connI[i+1]-connI[i]-1==3)
5451           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5452           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5453           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5454           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5455           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5456           if(eac)
5457             {
5458               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5459               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5460               delete eac;
5461               newConnIPtr[1]=(int)newConn.size();
5462             }
5463           else
5464             {
5465               types.insert(INTERP_KERNEL::NORM_SEG2);
5466               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5467               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5468               newConnIPtr[1]=newConnIPtr[0]+3;
5469             }
5470         }
5471       else
5472         {
5473           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5474           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5475           newConnIPtr[1]=newConnIPtr[0]+3;
5476         }
5477     }
5478   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5479     return ;
5480   _types=types;
5481   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5483   newConnArr->alloc((int)newConn.size(),1);
5484   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5485   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5486   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5487   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5488   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5489   std::copy(addCoo.begin(),addCoo.end(),work);
5490   DataArrayDouble::SetArrayIn(newCoords,_coords);
5491   updateTime();
5492 }
5493
5494 /*!
5495  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5496  * In addition, returns an array mapping new cells to old ones. <br>
5497  * This method typically increases the number of cells in \a this mesh
5498  * but the number of nodes remains \b unchanged.
5499  * That's why the 3D splitting policies
5500  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5501  *  \param [in] policy - specifies a pattern used for splitting.
5502  * The semantic of \a policy is:
5503  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5504  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5505  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5506  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5507  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5508  *          an id of old cell producing it. The caller is to delete this array using
5509  *         decrRef() as it is no more needed. 
5510  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5511  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5512  *          and \a this->getMeshDimension() != 3. 
5513  *  \throw If \a policy is not one of the four discussed above.
5514  *  \throw If the nodal connectivity of cells is not defined.
5515  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5516  */
5517 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5518 {
5519   switch(policy)
5520   {
5521     case 0:
5522       return simplexizePol0();
5523     case 1:
5524       return simplexizePol1();
5525     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5526         return simplexizePlanarFace5();
5527     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5528         return simplexizePlanarFace6();
5529     default:
5530       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)");
5531   }
5532 }
5533
5534 /*!
5535  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5536  * - 1D: INTERP_KERNEL::NORM_SEG2
5537  * - 2D: INTERP_KERNEL::NORM_TRI3
5538  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5539  *
5540  * This method is useful for users that need to use P1 field services as
5541  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5542  * All these methods need mesh support containing only simplex cells.
5543  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5544  *  \throw If the coordinates array is not set.
5545  *  \throw If the nodal connectivity of cells is not defined.
5546  *  \throw If \a this->getMeshDimension() < 1.
5547  */
5548 bool MEDCouplingUMesh::areOnlySimplexCells() const
5549 {
5550   checkFullyDefined();
5551   int mdim=getMeshDimension();
5552   if(mdim<1 || mdim>3)
5553     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5554   int nbCells=getNumberOfCells();
5555   const int *conn=_nodal_connec->getConstPointer();
5556   const int *connI=_nodal_connec_index->getConstPointer();
5557   for(int i=0;i<nbCells;i++)
5558     {
5559       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5560       if(!cm.isSimplex())
5561         return false;
5562     }
5563   return true;
5564 }
5565
5566 /*!
5567  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5568  */
5569 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5570 {
5571   checkConnectivityFullyDefined();
5572   if(getMeshDimension()!=2)
5573     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5574   int nbOfCells=getNumberOfCells();
5575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5576   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5577   ret->alloc(nbOfCells+nbOfCutCells,1);
5578   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5579   int *retPt=ret->getPointer();
5580   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5581   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5582   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5583   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5584   int *pt=newConn->getPointer();
5585   int *ptI=newConnI->getPointer();
5586   ptI[0]=0;
5587   const int *oldc=_nodal_connec->getConstPointer();
5588   const int *ci=_nodal_connec_index->getConstPointer();
5589   for(int i=0;i<nbOfCells;i++,ci++)
5590     {
5591       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5592         {
5593           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5594             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5595           pt=std::copy(tmp,tmp+8,pt);
5596           ptI[1]=ptI[0]+4;
5597           ptI[2]=ptI[0]+8;
5598           *retPt++=i;
5599           *retPt++=i;
5600           ptI+=2;
5601         }
5602       else
5603         {
5604           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5605           ptI[1]=ptI[0]+ci[1]-ci[0];
5606           ptI++;
5607           *retPt++=i;
5608         }
5609     }
5610   _nodal_connec->decrRef();
5611   _nodal_connec=newConn.retn();
5612   _nodal_connec_index->decrRef();
5613   _nodal_connec_index=newConnI.retn();
5614   computeTypes();
5615   updateTime();
5616   return ret.retn();
5617 }
5618
5619 /*!
5620  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5621  */
5622 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5623 {
5624   checkConnectivityFullyDefined();
5625   if(getMeshDimension()!=2)
5626     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5627   int nbOfCells=getNumberOfCells();
5628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5629   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5630   ret->alloc(nbOfCells+nbOfCutCells,1);
5631   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5632   int *retPt=ret->getPointer();
5633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5635   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5636   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5637   int *pt=newConn->getPointer();
5638   int *ptI=newConnI->getPointer();
5639   ptI[0]=0;
5640   const int *oldc=_nodal_connec->getConstPointer();
5641   const int *ci=_nodal_connec_index->getConstPointer();
5642   for(int i=0;i<nbOfCells;i++,ci++)
5643     {
5644       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5645         {
5646           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5647             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5648           pt=std::copy(tmp,tmp+8,pt);
5649           ptI[1]=ptI[0]+4;
5650           ptI[2]=ptI[0]+8;
5651           *retPt++=i;
5652           *retPt++=i;
5653           ptI+=2;
5654         }
5655       else
5656         {
5657           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5658           ptI[1]=ptI[0]+ci[1]-ci[0];
5659           ptI++;
5660           *retPt++=i;
5661         }
5662     }
5663   _nodal_connec->decrRef();
5664   _nodal_connec=newConn.retn();
5665   _nodal_connec_index->decrRef();
5666   _nodal_connec_index=newConnI.retn();
5667   computeTypes();
5668   updateTime();
5669   return ret.retn();
5670 }
5671
5672 /*!
5673  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5674  */
5675 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5676 {
5677   checkConnectivityFullyDefined();
5678   if(getMeshDimension()!=3)
5679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5680   int nbOfCells=getNumberOfCells();
5681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5682   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5683   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5684   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5685   int *retPt=ret->getPointer();
5686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5688   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5689   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5690   int *pt=newConn->getPointer();
5691   int *ptI=newConnI->getPointer();
5692   ptI[0]=0;
5693   const int *oldc=_nodal_connec->getConstPointer();
5694   const int *ci=_nodal_connec_index->getConstPointer();
5695   for(int i=0;i<nbOfCells;i++,ci++)
5696     {
5697       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5698         {
5699           for(int j=0;j<5;j++,pt+=5,ptI++)
5700             {
5701               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5702               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];
5703               *retPt++=i;
5704               ptI[1]=ptI[0]+5;
5705             }
5706         }
5707       else
5708         {
5709           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5710           ptI[1]=ptI[0]+ci[1]-ci[0];
5711           ptI++;
5712           *retPt++=i;
5713         }
5714     }
5715   _nodal_connec->decrRef();
5716   _nodal_connec=newConn.retn();
5717   _nodal_connec_index->decrRef();
5718   _nodal_connec_index=newConnI.retn();
5719   computeTypes();
5720   updateTime();
5721   return ret.retn();
5722 }
5723
5724 /*!
5725  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5726  */
5727 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5728 {
5729   checkConnectivityFullyDefined();
5730   if(getMeshDimension()!=3)
5731     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5732   int nbOfCells=getNumberOfCells();
5733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5734   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5735   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5736   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5737   int *retPt=ret->getPointer();
5738   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5739   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5740   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5741   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5742   int *pt=newConn->getPointer();
5743   int *ptI=newConnI->getPointer();
5744   ptI[0]=0;
5745   const int *oldc=_nodal_connec->getConstPointer();
5746   const int *ci=_nodal_connec_index->getConstPointer();
5747   for(int i=0;i<nbOfCells;i++,ci++)
5748     {
5749       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5750         {
5751           for(int j=0;j<6;j++,pt+=5,ptI++)
5752             {
5753               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5754               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];
5755               *retPt++=i;
5756               ptI[1]=ptI[0]+5;
5757             }
5758         }
5759       else
5760         {
5761           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5762           ptI[1]=ptI[0]+ci[1]-ci[0];
5763           ptI++;
5764           *retPt++=i;
5765         }
5766     }
5767   _nodal_connec->decrRef();
5768   _nodal_connec=newConn.retn();
5769   _nodal_connec_index->decrRef();
5770   _nodal_connec_index=newConnI.retn();
5771   computeTypes();
5772   updateTime();
5773   return ret.retn();
5774 }
5775
5776 /*!
5777  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5778  * This method completly ignore coordinates.
5779  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5780  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5781  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5782  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5783  */
5784 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5785 {
5786   checkFullyDefined();
5787   if(getMeshDimension()!=2)
5788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5789   int nbOfCells=getNumberOfCells();
5790   int *connI=_nodal_connec_index->getPointer();
5791   int newConnLgth=0;
5792   for(int i=0;i<nbOfCells;i++,connI++)
5793     {
5794       int offset=descIndex[i];
5795       int nbOfEdges=descIndex[i+1]-offset;
5796       //
5797       bool ddirect=desc[offset+nbOfEdges-1]>0;
5798       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5799       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5800       for(int j=0;j<nbOfEdges;j++)
5801         {
5802           bool direct=desc[offset+j]>0;
5803           int edgeId=std::abs(desc[offset+j])-1;
5804           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5805             {
5806               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5807               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5808               int ref2=direct?id1:id2;
5809               if(ref==ref2)
5810                 {
5811                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5812                   newConnLgth+=nbOfSubNodes-1;
5813                   ref=direct?id2:id1;
5814                 }
5815               else
5816                 {
5817                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5818                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5819                 }
5820             }
5821           else
5822             {
5823               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5824             }
5825         }
5826       newConnLgth++;//+1 is for cell type
5827       connI[1]=newConnLgth;
5828     }
5829   //
5830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5831   newConn->alloc(newConnLgth,1);
5832   int *work=newConn->getPointer();
5833   for(int i=0;i<nbOfCells;i++)
5834     {
5835       *work++=INTERP_KERNEL::NORM_POLYGON;
5836       int offset=descIndex[i];
5837       int nbOfEdges=descIndex[i+1]-offset;
5838       for(int j=0;j<nbOfEdges;j++)
5839         {
5840           bool direct=desc[offset+j]>0;
5841           int edgeId=std::abs(desc[offset+j])-1;
5842           if(direct)
5843             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5844           else
5845             {
5846               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5847               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5848               work=std::copy(it,it+nbOfSubNodes-1,work);
5849             }
5850         }
5851     }
5852   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5853   _types.clear();
5854   if(nbOfCells>0)
5855     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5856 }
5857
5858 /*!
5859  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5860  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5861  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5862  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5863  * so it can be useful to call mergeNodes() before calling this method.
5864  *  \throw If \a this->getMeshDimension() <= 1.
5865  *  \throw If the coordinates array is not set.
5866  *  \throw If the nodal connectivity of cells is not defined.
5867  */
5868 void MEDCouplingUMesh::convertDegeneratedCells()
5869 {
5870   checkFullyDefined();
5871   if(getMeshDimension()<=1)
5872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5873   int nbOfCells=getNumberOfCells();
5874   if(nbOfCells<1)
5875     return ;
5876   int initMeshLgth=getMeshLength();
5877   int *conn=_nodal_connec->getPointer();
5878   int *index=_nodal_connec_index->getPointer();
5879   int posOfCurCell=0;
5880   int newPos=0;
5881   int lgthOfCurCell;
5882   for(int i=0;i<nbOfCells;i++)
5883     {
5884       lgthOfCurCell=index[i+1]-posOfCurCell;
5885       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5886       int newLgth;
5887       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5888                                                                                                      conn+newPos+1,newLgth);
5889       conn[newPos]=newType;
5890       newPos+=newLgth+1;
5891       posOfCurCell=index[i+1];
5892       index[i+1]=newPos;
5893     }
5894   if(newPos!=initMeshLgth)
5895     _nodal_connec->reAlloc(newPos);
5896   computeTypes();
5897 }
5898
5899 /*!
5900  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5901  * A cell is considered to be oriented correctly if an angle between its
5902  * normal vector and a given vector is less than \c PI / \c 2.
5903  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5904  *         cells. 
5905  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5906  *         checked.
5907  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5908  *         is not cleared before filling in.
5909  *  \throw If \a this->getMeshDimension() != 2.
5910  *  \throw If \a this->getSpaceDimension() != 3.
5911  *
5912  *  \if ENABLE_EXAMPLES
5913  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5914  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5915  *  \endif
5916  */
5917 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5918 {
5919   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5920     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5921   int nbOfCells=getNumberOfCells();
5922   const int *conn=_nodal_connec->getConstPointer();
5923   const int *connI=_nodal_connec_index->getConstPointer();
5924   const double *coordsPtr=_coords->getConstPointer();
5925   for(int i=0;i<nbOfCells;i++)
5926     {
5927       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5928       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5929         {
5930           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5931           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5932             cells.push_back(i);
5933         }
5934     }
5935 }
5936
5937 /*!
5938  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5939  * considered to be oriented correctly if an angle between its normal vector and a
5940  * given vector is less than \c PI / \c 2. 
5941  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5942  *         cells. 
5943  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5944  *         checked.
5945  *  \throw If \a this->getMeshDimension() != 2.
5946  *  \throw If \a this->getSpaceDimension() != 3.
5947  *
5948  *  \if ENABLE_EXAMPLES
5949  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5950  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5951  *  \endif
5952  */
5953 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5954 {
5955   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5956     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5957   int nbOfCells=getNumberOfCells();
5958   int *conn=_nodal_connec->getPointer();
5959   const int *connI=_nodal_connec_index->getConstPointer();
5960   const double *coordsPtr=_coords->getConstPointer();
5961   bool isModified=false;
5962   for(int i=0;i<nbOfCells;i++)
5963     {
5964       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5965       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5966         {
5967           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5968           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5969             {
5970               isModified=true;
5971               if(!isQuadratic)
5972                 {
5973                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5974                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5975                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5976                 }
5977               else
5978                 {
5979                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5980                   std::vector<int> tmp0(sz-1),tmp1(sz);
5981                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5982                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5983                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5984                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5985                 }
5986             }
5987         }
5988     }
5989   if(isModified)
5990     _nodal_connec->declareAsNew();
5991   updateTime();
5992 }
5993
5994 /*!
5995  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5996  * oriented facets. The normal vector of the facet should point out of the cell.
5997  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5998  *         is not cleared before filling in.
5999  *  \throw If \a this->getMeshDimension() != 3.
6000  *  \throw If \a this->getSpaceDimension() != 3.
6001  *  \throw If the coordinates array is not set.
6002  *  \throw If the nodal connectivity of cells is not defined.
6003  *
6004  *  \if ENABLE_EXAMPLES
6005  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6006  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6007  *  \endif
6008  */
6009 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6010 {
6011   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6012     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6013   int nbOfCells=getNumberOfCells();
6014   const int *conn=_nodal_connec->getConstPointer();
6015   const int *connI=_nodal_connec_index->getConstPointer();
6016   const double *coordsPtr=_coords->getConstPointer();
6017   for(int i=0;i<nbOfCells;i++)
6018     {
6019       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6020       if(type==INTERP_KERNEL::NORM_POLYHED)
6021         {
6022           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6023             cells.push_back(i);
6024         }
6025     }
6026 }
6027
6028 /*!
6029  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6030  * out of the cell. 
6031  *  \throw If \a this->getMeshDimension() != 3.
6032  *  \throw If \a this->getSpaceDimension() != 3.
6033  *  \throw If the coordinates array is not set.
6034  *  \throw If the nodal connectivity of cells is not defined.
6035  *  \throw If the reparation fails.
6036  *
6037  *  \if ENABLE_EXAMPLES
6038  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6039  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6040  *  \endif
6041  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6042  */
6043 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6044 {
6045   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6046     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6047   int nbOfCells=getNumberOfCells();
6048   int *conn=_nodal_connec->getPointer();
6049   const int *connI=_nodal_connec_index->getConstPointer();
6050   const double *coordsPtr=_coords->getConstPointer();
6051   for(int i=0;i<nbOfCells;i++)
6052     {
6053       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6054       if(type==INTERP_KERNEL::NORM_POLYHED)
6055         {
6056           try
6057           {
6058               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6059                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6060           }
6061           catch(INTERP_KERNEL::Exception& e)
6062           {
6063               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6064               throw INTERP_KERNEL::Exception(oss.str().c_str());
6065           }
6066         }
6067     }
6068   updateTime();
6069 }
6070
6071 /*!
6072  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6073  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6074  * according to which the first facet of the cell should be oriented to have the normal vector
6075  * pointing out of cell.
6076  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6077  *         cells. The caller is to delete this array using decrRef() as it is no more
6078  *         needed. 
6079  *  \throw If \a this->getMeshDimension() != 3.
6080  *  \throw If \a this->getSpaceDimension() != 3.
6081  *  \throw If the coordinates array is not set.
6082  *  \throw If the nodal connectivity of cells is not defined.
6083  *
6084  *  \if ENABLE_EXAMPLES
6085  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6086  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6087  *  \endif
6088  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6089  */
6090 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6091 {
6092   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6093   if(getMeshDimension()!=3)
6094     throw INTERP_KERNEL::Exception(msg);
6095   int spaceDim=getSpaceDimension();
6096   if(spaceDim!=3)
6097     throw INTERP_KERNEL::Exception(msg);
6098   //
6099   int nbOfCells=getNumberOfCells();
6100   int *conn=_nodal_connec->getPointer();
6101   const int *connI=_nodal_connec_index->getConstPointer();
6102   const double *coo=getCoords()->getConstPointer();
6103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6104   for(int i=0;i<nbOfCells;i++)
6105     {
6106       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6107       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6108         {
6109           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6110             {
6111               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6112               cells->pushBackSilent(i);
6113             }
6114         }
6115     }
6116   return cells.retn();
6117 }
6118
6119 /*!
6120  * This method is a faster method to correct orientation of all 3D cells in \a this.
6121  * 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.
6122  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6123  * 
6124  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6125  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6126  */
6127 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6128 {
6129   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6130     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6131   int nbOfCells=getNumberOfCells();
6132   int *conn=_nodal_connec->getPointer();
6133   const int *connI=_nodal_connec_index->getConstPointer();
6134   const double *coordsPtr=_coords->getConstPointer();
6135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6136   for(int i=0;i<nbOfCells;i++)
6137     {
6138       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6139       switch(type)
6140       {
6141         case INTERP_KERNEL::NORM_TETRA4:
6142           {
6143             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6144               {
6145                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6146                 ret->pushBackSilent(i);
6147               }
6148             break;
6149           }
6150         case INTERP_KERNEL::NORM_PYRA5:
6151           {
6152             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6153               {
6154                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6155                 ret->pushBackSilent(i);
6156               }
6157             break;
6158           }
6159         case INTERP_KERNEL::NORM_PENTA6:
6160         case INTERP_KERNEL::NORM_HEXA8:
6161         case INTERP_KERNEL::NORM_HEXGP12:
6162           {
6163             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6164               {
6165                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6166                 ret->pushBackSilent(i);
6167               }
6168             break;
6169           }
6170         case INTERP_KERNEL::NORM_POLYHED:
6171           {
6172             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6173               {
6174                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6175                 ret->pushBackSilent(i);
6176               }
6177             break;
6178           }
6179         default:
6180           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 !");
6181       }
6182     }
6183   updateTime();
6184   return ret.retn();
6185 }
6186
6187 /*!
6188  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6189  * If it is not the case an exception will be thrown.
6190  * This method is fast because the first cell of \a this is used to compute the plane.
6191  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6192  * \param pos output of size at least 3 used to store a point owned of searched plane.
6193  */
6194 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6195 {
6196   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6197     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6198   const int *conn=_nodal_connec->getConstPointer();
6199   const int *connI=_nodal_connec_index->getConstPointer();
6200   const double *coordsPtr=_coords->getConstPointer();
6201   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6202   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6203 }
6204
6205 /*!
6206  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6207  * cells. Currently cells of the following types are treated:
6208  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6209  * For a cell of other type an exception is thrown.
6210  * Space dimension of a 2D mesh can be either 2 or 3.
6211  * The Edge Ratio of a cell \f$t\f$ is: 
6212  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6213  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6214  *  the smallest edge lengths of \f$t\f$.
6215  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6216  *          cells and one time, lying on \a this mesh. The caller is to delete this
6217  *          field using decrRef() as it is no more needed. 
6218  *  \throw If the coordinates array is not set.
6219  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6220  *  \throw If the connectivity data array has more than one component.
6221  *  \throw If the connectivity data array has a named component.
6222  *  \throw If the connectivity index data array has more than one component.
6223  *  \throw If the connectivity index data array has a named component.
6224  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6225  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6226  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6227  */
6228 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6229 {
6230   checkCoherency();
6231   int spaceDim=getSpaceDimension();
6232   int meshDim=getMeshDimension();
6233   if(spaceDim!=2 && spaceDim!=3)
6234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6235   if(meshDim!=2 && meshDim!=3)
6236     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6237   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6238   ret->setMesh(this);
6239   int nbOfCells=getNumberOfCells();
6240   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6241   arr->alloc(nbOfCells,1);
6242   double *pt=arr->getPointer();
6243   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6244   const int *conn=_nodal_connec->getConstPointer();
6245   const int *connI=_nodal_connec_index->getConstPointer();
6246   const double *coo=_coords->getConstPointer();
6247   double tmp[12];
6248   for(int i=0;i<nbOfCells;i++,pt++)
6249     {
6250       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6251       switch(t)
6252       {
6253         case INTERP_KERNEL::NORM_TRI3:
6254           {
6255             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6256             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6257             break;
6258           }
6259         case INTERP_KERNEL::NORM_QUAD4:
6260           {
6261             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6262             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6263             break;
6264           }
6265         case INTERP_KERNEL::NORM_TETRA4:
6266           {
6267             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6268             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6269             break;
6270           }
6271         default:
6272           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6273       }
6274       conn+=connI[i+1]-connI[i];
6275     }
6276   ret->setName("EdgeRatio");
6277   ret->synchronizeTimeWithSupport();
6278   return ret.retn();
6279 }
6280
6281 /*!
6282  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6283  * cells. Currently cells of the following types are treated:
6284  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6285  * For a cell of other type an exception is thrown.
6286  * Space dimension of a 2D mesh can be either 2 or 3.
6287  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6288  *          cells and one time, lying on \a this mesh. The caller is to delete this
6289  *          field using decrRef() as it is no more needed. 
6290  *  \throw If the coordinates array is not set.
6291  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6292  *  \throw If the connectivity data array has more than one component.
6293  *  \throw If the connectivity data array has a named component.
6294  *  \throw If the connectivity index data array has more than one component.
6295  *  \throw If the connectivity index data array has a named component.
6296  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6297  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6298  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6299  */
6300 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6301 {
6302   checkCoherency();
6303   int spaceDim=getSpaceDimension();
6304   int meshDim=getMeshDimension();
6305   if(spaceDim!=2 && spaceDim!=3)
6306     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6307   if(meshDim!=2 && meshDim!=3)
6308     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6309   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6310   ret->setMesh(this);
6311   int nbOfCells=getNumberOfCells();
6312   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6313   arr->alloc(nbOfCells,1);
6314   double *pt=arr->getPointer();
6315   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6316   const int *conn=_nodal_connec->getConstPointer();
6317   const int *connI=_nodal_connec_index->getConstPointer();
6318   const double *coo=_coords->getConstPointer();
6319   double tmp[12];
6320   for(int i=0;i<nbOfCells;i++,pt++)
6321     {
6322       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6323       switch(t)
6324       {
6325         case INTERP_KERNEL::NORM_TRI3:
6326           {
6327             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6328             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6329             break;
6330           }
6331         case INTERP_KERNEL::NORM_QUAD4:
6332           {
6333             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6334             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6335             break;
6336           }
6337         case INTERP_KERNEL::NORM_TETRA4:
6338           {
6339             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6340             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6341             break;
6342           }
6343         default:
6344           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6345       }
6346       conn+=connI[i+1]-connI[i];
6347     }
6348   ret->setName("AspectRatio");
6349   ret->synchronizeTimeWithSupport();
6350   return ret.retn();
6351 }
6352
6353 /*!
6354  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6355  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6356  * treated: INTERP_KERNEL::NORM_QUAD4.
6357  * For a cell of other type an exception is thrown.
6358  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6359  *          cells and one time, lying on \a this mesh. The caller is to delete this
6360  *          field using decrRef() as it is no more needed. 
6361  *  \throw If the coordinates array is not set.
6362  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6363  *  \throw If the connectivity data array has more than one component.
6364  *  \throw If the connectivity data array has a named component.
6365  *  \throw If the connectivity index data array has more than one component.
6366  *  \throw If the connectivity index data array has a named component.
6367  *  \throw If \a this->getMeshDimension() != 2.
6368  *  \throw If \a this->getSpaceDimension() != 3.
6369  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6370  */
6371 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6372 {
6373   checkCoherency();
6374   int spaceDim=getSpaceDimension();
6375   int meshDim=getMeshDimension();
6376   if(spaceDim!=3)
6377     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6378   if(meshDim!=2)
6379     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6380   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6381   ret->setMesh(this);
6382   int nbOfCells=getNumberOfCells();
6383   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6384   arr->alloc(nbOfCells,1);
6385   double *pt=arr->getPointer();
6386   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6387   const int *conn=_nodal_connec->getConstPointer();
6388   const int *connI=_nodal_connec_index->getConstPointer();
6389   const double *coo=_coords->getConstPointer();
6390   double tmp[12];
6391   for(int i=0;i<nbOfCells;i++,pt++)
6392     {
6393       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6394       switch(t)
6395       {
6396         case INTERP_KERNEL::NORM_QUAD4:
6397           {
6398             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6399             *pt=INTERP_KERNEL::quadWarp(tmp);
6400             break;
6401           }
6402         default:
6403           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6404       }
6405       conn+=connI[i+1]-connI[i];
6406     }
6407   ret->setName("Warp");
6408   ret->synchronizeTimeWithSupport();
6409   return ret.retn();
6410 }
6411
6412
6413 /*!
6414  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6415  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6416  * treated: INTERP_KERNEL::NORM_QUAD4.
6417  * For a cell of other type an exception is thrown.
6418  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6419  *          cells and one time, lying on \a this mesh. The caller is to delete this
6420  *          field using decrRef() as it is no more needed. 
6421  *  \throw If the coordinates array is not set.
6422  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6423  *  \throw If the connectivity data array has more than one component.
6424  *  \throw If the connectivity data array has a named component.
6425  *  \throw If the connectivity index data array has more than one component.
6426  *  \throw If the connectivity index data array has a named component.
6427  *  \throw If \a this->getMeshDimension() != 2.
6428  *  \throw If \a this->getSpaceDimension() != 3.
6429  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6430  */
6431 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6432 {
6433   checkCoherency();
6434   int spaceDim=getSpaceDimension();
6435   int meshDim=getMeshDimension();
6436   if(spaceDim!=3)
6437     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6438   if(meshDim!=2)
6439     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6440   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6441   ret->setMesh(this);
6442   int nbOfCells=getNumberOfCells();
6443   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6444   arr->alloc(nbOfCells,1);
6445   double *pt=arr->getPointer();
6446   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6447   const int *conn=_nodal_connec->getConstPointer();
6448   const int *connI=_nodal_connec_index->getConstPointer();
6449   const double *coo=_coords->getConstPointer();
6450   double tmp[12];
6451   for(int i=0;i<nbOfCells;i++,pt++)
6452     {
6453       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6454       switch(t)
6455       {
6456         case INTERP_KERNEL::NORM_QUAD4:
6457           {
6458             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6459             *pt=INTERP_KERNEL::quadSkew(tmp);
6460             break;
6461           }
6462         default:
6463           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6464       }
6465       conn+=connI[i+1]-connI[i];
6466     }
6467   ret->setName("Skew");
6468   ret->synchronizeTimeWithSupport();
6469   return ret.retn();
6470 }
6471
6472 /*!
6473  * This method aggregate the bbox of each cell and put it into bbox parameter.
6474  * 
6475  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6476  *                         For all other cases this input parameter is ignored.
6477  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6478  * 
6479  * \throw If \a this is not fully set (coordinates and connectivity).
6480  * \throw If a cell in \a this has no valid nodeId.
6481  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6482  */
6483 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6484 {
6485   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6486   if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3))  // Compute refined boundary box for quadratic elements only in 2D.
6487     return getBoundingBoxForBBTreeFast();
6488   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6489     {
6490       bool presenceOfQuadratic(false);
6491       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6492         {
6493           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6494           if(cm.isQuadratic())
6495             presenceOfQuadratic=true;
6496         }
6497       if(!presenceOfQuadratic)
6498         return getBoundingBoxForBBTreeFast();
6499       if(mDim==2 && sDim==2)
6500         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6501       else
6502         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6503     }
6504   throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6505 }
6506
6507 /*!
6508  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6509  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6510  * 
6511  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6512  * 
6513  * \throw If \a this is not fully set (coordinates and connectivity).
6514  * \throw If a cell in \a this has no valid nodeId.
6515  */
6516 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6517 {
6518   checkFullyDefined();
6519   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6520   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6521   double *bbox(ret->getPointer());
6522   for(int i=0;i<nbOfCells*spaceDim;i++)
6523     {
6524       bbox[2*i]=std::numeric_limits<double>::max();
6525       bbox[2*i+1]=-std::numeric_limits<double>::max();
6526     }
6527   const double *coordsPtr(_coords->getConstPointer());
6528   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6529   for(int i=0;i<nbOfCells;i++)
6530     {
6531       int offset=connI[i]+1;
6532       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6533       for(int j=0;j<nbOfNodesForCell;j++)
6534         {
6535           int nodeId=conn[offset+j];
6536           if(nodeId>=0 && nodeId<nbOfNodes)
6537             {
6538               for(int k=0;k<spaceDim;k++)
6539                 {
6540                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6541                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6542                 }
6543               kk++;
6544             }
6545         }
6546       if(kk==0)
6547         {
6548           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6549           throw INTERP_KERNEL::Exception(oss.str().c_str());
6550         }
6551     }
6552   return ret.retn();
6553 }
6554
6555 /*!
6556  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6557  * useful for 2D meshes having quadratic cells
6558  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6559  * the two extremities of the arc of circle).
6560  * 
6561  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6562  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6563  * \throw If \a this is not fully defined.
6564  * \throw If \a this is not a mesh with meshDimension equal to 2.
6565  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6566  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6567  */
6568 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6569 {
6570   checkFullyDefined();
6571   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6572   if(spaceDim!=2 || mDim!=2)
6573     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6574   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6575   double *bbox(ret->getPointer());
6576   const double *coords(_coords->getConstPointer());
6577   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6578   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6579     {
6580       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6581       int sz(connI[1]-connI[0]-1);
6582       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6583       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6584       INTERP_KERNEL::QuadraticPolygon *pol(0);
6585       for(int j=0;j<sz;j++)
6586         {
6587           int nodeId(conn[*connI+1+j]);
6588           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6589         }
6590       if(!cm.isQuadratic())
6591         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6592       else
6593         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6594       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6595       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6596     }
6597   return ret.retn();
6598 }
6599
6600 /*!
6601  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6602  * useful for 2D meshes having quadratic cells
6603  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6604  * the two extremities of the arc of circle).
6605  * 
6606  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6607  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6608  * \throw If \a this is not fully defined.
6609  * \throw If \a this is not a mesh with meshDimension equal to 1.
6610  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6611  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6612  */
6613 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6614 {
6615   checkFullyDefined();
6616   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6617   if(spaceDim!=2 || mDim!=1)
6618     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6619   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6620   double *bbox(ret->getPointer());
6621   const double *coords(_coords->getConstPointer());
6622   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6623   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6624     {
6625       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6626       int sz(connI[1]-connI[0]-1);
6627       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6628       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6629       INTERP_KERNEL::Edge *edge(0);
6630       for(int j=0;j<sz;j++)
6631         {
6632           int nodeId(conn[*connI+1+j]);
6633           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6634         }
6635       if(!cm.isQuadratic())
6636         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6637       else
6638         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6639       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6640       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6641     }
6642   return ret.retn();
6643 }
6644
6645 /// @cond INTERNAL
6646
6647 namespace ParaMEDMEMImpl
6648 {
6649   class ConnReader
6650   {
6651   public:
6652     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6653     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6654   private:
6655     const int *_conn;
6656     int _val;
6657   };
6658
6659   class ConnReader2
6660   {
6661   public:
6662     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6663     bool operator() (const int& pos) { return _conn[pos]==_val; }
6664   private:
6665     const int *_conn;
6666     int _val;
6667   };
6668 }
6669
6670 /// @endcond
6671
6672 /*!
6673  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6674  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6675  * \a this is composed in cell types.
6676  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6677  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6678  * This parameter is kept only for compatibility with other methode listed above.
6679  */
6680 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6681 {
6682   checkConnectivityFullyDefined();
6683   const int *conn=_nodal_connec->getConstPointer();
6684   const int *connI=_nodal_connec_index->getConstPointer();
6685   const int *work=connI;
6686   int nbOfCells=getNumberOfCells();
6687   std::size_t n=getAllGeoTypes().size();
6688   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6689   std::set<INTERP_KERNEL::NormalizedCellType> types;
6690   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6691     {
6692       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6693       if(types.find(typ)!=types.end())
6694         {
6695           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6696           oss << " is not contiguous !";
6697           throw INTERP_KERNEL::Exception(oss.str().c_str());
6698         }
6699       types.insert(typ);
6700       ret[3*i]=typ;
6701       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6702       ret[3*i+1]=(int)std::distance(work,work2);
6703       work=work2;
6704     }
6705   return ret;
6706 }
6707
6708 /*!
6709  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6710  * only for types cell, type node is not managed.
6711  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6712  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6713  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6714  * If 2 or more same geometric type is in \a code and exception is thrown too.
6715  *
6716  * This method firstly checks
6717  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6718  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6719  * an exception is thrown too.
6720  * 
6721  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6722  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6723  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6724  */
6725 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6726 {
6727   if(code.empty())
6728     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6729   std::size_t sz=code.size();
6730   std::size_t n=sz/3;
6731   if(sz%3!=0)
6732     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6733   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6734   int nb=0;
6735   bool isNoPflUsed=true;
6736   for(std::size_t i=0;i<n;i++)
6737     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6738       {
6739         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6740         nb+=code[3*i+1];
6741         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6742           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6743         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6744       }
6745   if(types.size()!=n)
6746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6747   if(isNoPflUsed)
6748     {
6749       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6750         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6751       if(types.size()==_types.size())
6752         return 0;
6753     }
6754   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6755   ret->alloc(nb,1);
6756   int *retPtr=ret->getPointer();
6757   const int *connI=_nodal_connec_index->getConstPointer();
6758   const int *conn=_nodal_connec->getConstPointer();
6759   int nbOfCells=getNumberOfCells();
6760   const int *i=connI;
6761   int kk=0;
6762   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6763     {
6764       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6765       int offset=(int)std::distance(connI,i);
6766       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6767       int nbOfCellsOfCurType=(int)std::distance(i,j);
6768       if(code[3*kk+2]==-1)
6769         for(int k=0;k<nbOfCellsOfCurType;k++)
6770           *retPtr++=k+offset;
6771       else
6772         {
6773           int idInIdsPerType=code[3*kk+2];
6774           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6775             {
6776               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6777               if(zePfl)
6778                 {
6779                   zePfl->checkAllocated();
6780                   if(zePfl->getNumberOfComponents()==1)
6781                     {
6782                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6783                         {
6784                           if(*k>=0 && *k<nbOfCellsOfCurType)
6785                             *retPtr=(*k)+offset;
6786                           else
6787                             {
6788                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6789                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6790                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6791                             }
6792                         }
6793                     }
6794                   else
6795                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6796                 }
6797               else
6798                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6799             }
6800           else
6801             {
6802               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6803               oss << " should be in [0," << idsPerType.size() << ") !";
6804               throw INTERP_KERNEL::Exception(oss.str().c_str());
6805             }
6806         }
6807       i=j;
6808     }
6809   return ret.retn();
6810 }
6811
6812 /*!
6813  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6814  * 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.
6815  * 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.
6816  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6817  * 
6818  * \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.
6819  * \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,
6820  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6821  * \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.
6822  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6823  * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6824  */
6825 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6826 {
6827   if(!profile)
6828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6829   if(profile->getNumberOfComponents()!=1)
6830     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6831   checkConnectivityFullyDefined();
6832   const int *conn=_nodal_connec->getConstPointer();
6833   const int *connI=_nodal_connec_index->getConstPointer();
6834   int nbOfCells=getNumberOfCells();
6835   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6836   std::vector<int> typeRangeVals(1);
6837   for(const int *i=connI;i!=connI+nbOfCells;)
6838     {
6839       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6840       if(std::find(types.begin(),types.end(),curType)!=types.end())
6841         {
6842           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6843         }
6844       types.push_back(curType);
6845       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6846       typeRangeVals.push_back((int)std::distance(connI,i));
6847     }
6848   //
6849   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6850   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6854   //
6855   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6856   code.resize(3*nbOfCastsFinal);
6857   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6858   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6859   for(int i=0;i<nbOfCastsFinal;i++)
6860     {
6861       int castId=castsPresent->getIJ(i,0);
6862       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6863       idsInPflPerType2.push_back(tmp3);
6864       code[3*i]=(int)types[castId];
6865       code[3*i+1]=tmp3->getNumberOfTuples();
6866       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6867       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6868         {
6869           tmp4->copyStringInfoFrom(*profile);
6870           idsPerType2.push_back(tmp4);
6871           code[3*i+2]=(int)idsPerType2.size()-1;
6872         }
6873       else
6874         {
6875           code[3*i+2]=-1;
6876         }
6877     }
6878   std::size_t sz2=idsInPflPerType2.size();
6879   idsInPflPerType.resize(sz2);
6880   for(std::size_t i=0;i<sz2;i++)
6881     {
6882       DataArrayInt *locDa=idsInPflPerType2[i];
6883       locDa->incrRef();
6884       idsInPflPerType[i]=locDa;
6885     }
6886   std::size_t sz=idsPerType2.size();
6887   idsPerType.resize(sz);
6888   for(std::size_t i=0;i<sz;i++)
6889     {
6890       DataArrayInt *locDa=idsPerType2[i];
6891       locDa->incrRef();
6892       idsPerType[i]=locDa;
6893     }
6894 }
6895
6896 /*!
6897  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6898  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6899  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6900  * 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.
6901  */
6902 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6903 {
6904   checkFullyDefined();
6905   nM1LevMesh->checkFullyDefined();
6906   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6908   if(_coords!=nM1LevMesh->getCoords())
6909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6912   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6914   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6916   tmp->setConnectivity(tmp0,tmp1);
6917   tmp->renumberCells(ret0->getConstPointer(),false);
6918   revDesc=tmp->getNodalConnectivity();
6919   revDescIndx=tmp->getNodalConnectivityIndex();
6920   DataArrayInt *ret=0;
6921   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6922     {
6923       int tmp2;
6924       ret->getMaxValue(tmp2);
6925       ret->decrRef();
6926       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6927       throw INTERP_KERNEL::Exception(oss.str().c_str());
6928     }
6929   nM1LevMeshIds=ret;
6930   //
6931   revDesc->incrRef();
6932   revDescIndx->incrRef();
6933   ret1->incrRef();
6934   ret0->incrRef();
6935   meshnM1Old2New=ret0;
6936   return ret1;
6937 }
6938
6939 /*!
6940  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6941  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6942  * in "Old to New" mode.
6943  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6944  *          this array using decrRef() as it is no more needed.
6945  *  \throw If the nodal connectivity of cells is not defined.
6946  */
6947 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6948 {
6949   checkConnectivityFullyDefined();
6950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6951   renumberCells(ret->getConstPointer(),false);
6952   return ret.retn();
6953 }
6954
6955 /*!
6956  * This methods checks that cells are sorted by their types.
6957  * This method makes asumption (no check) that connectivity is correctly set before calling.
6958  */
6959 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6960 {
6961   checkFullyDefined();
6962   const int *conn=_nodal_connec->getConstPointer();
6963   const int *connI=_nodal_connec_index->getConstPointer();
6964   int nbOfCells=getNumberOfCells();
6965   std::set<INTERP_KERNEL::NormalizedCellType> types;
6966   for(const int *i=connI;i!=connI+nbOfCells;)
6967     {
6968       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6969       if(types.find(curType)!=types.end())
6970         return false;
6971       types.insert(curType);
6972       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6973     }
6974   return true;
6975 }
6976
6977 /*!
6978  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6979  * The geometric type order is specified by MED file.
6980  * 
6981  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6982  */
6983 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6984 {
6985   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6986 }
6987
6988 /*!
6989  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6990  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6991  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6992  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6993  */
6994 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6995 {
6996   checkFullyDefined();
6997   const int *conn=_nodal_connec->getConstPointer();
6998   const int *connI=_nodal_connec_index->getConstPointer();
6999   int nbOfCells=getNumberOfCells();
7000   if(nbOfCells==0)
7001     return true;
7002   int lastPos=-1;
7003   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7004   for(const int *i=connI;i!=connI+nbOfCells;)
7005     {
7006       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7007       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7008       if(isTypeExists!=orderEnd)
7009         {
7010           int pos=(int)std::distance(orderBg,isTypeExists);
7011           if(pos<=lastPos)
7012             return false;
7013           lastPos=pos;
7014           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7015         }
7016       else
7017         {
7018           if(sg.find(curType)==sg.end())
7019             {
7020               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7021               sg.insert(curType);
7022             }
7023           else
7024             return false;
7025         }
7026     }
7027   return true;
7028 }
7029
7030 /*!
7031  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7032  * 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
7033  * 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'.
7034  */
7035 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7036 {
7037   checkConnectivityFullyDefined();
7038   int nbOfCells=getNumberOfCells();
7039   const int *conn=_nodal_connec->getConstPointer();
7040   const int *connI=_nodal_connec_index->getConstPointer();
7041   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7042   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7043   tmpa->alloc(nbOfCells,1);
7044   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7045   tmpb->fillWithZero();
7046   int *tmp=tmpa->getPointer();
7047   int *tmp2=tmpb->getPointer();
7048   for(const int *i=connI;i!=connI+nbOfCells;i++)
7049     {
7050       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7051       if(where!=orderEnd)
7052         {
7053           int pos=(int)std::distance(orderBg,where);
7054           tmp2[pos]++;
7055           tmp[std::distance(connI,i)]=pos;
7056         }
7057       else
7058         {
7059           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7060           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7061           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7062           throw INTERP_KERNEL::Exception(oss.str().c_str());
7063         }
7064     }
7065   nbPerType=tmpb.retn();
7066   return tmpa.retn();
7067 }
7068
7069 /*!
7070  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7071  *
7072  * \return a new object containing the old to new correspondance.
7073  *
7074  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7075  */
7076 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7077 {
7078   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7079 }
7080
7081 /*!
7082  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
7083  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7084  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7085  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7086  */
7087 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7088 {
7089   DataArrayInt *nbPerType=0;
7090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7091   nbPerType->decrRef();
7092   return tmpa->buildPermArrPerLevel();
7093 }
7094
7095 /*!
7096  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7097  * The number of cells remains unchanged after the call of this method.
7098  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7099  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7100  *
7101  * \return the array giving the correspondance old to new.
7102  */
7103 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7104 {
7105   checkFullyDefined();
7106   computeTypes();
7107   const int *conn=_nodal_connec->getConstPointer();
7108   const int *connI=_nodal_connec_index->getConstPointer();
7109   int nbOfCells=getNumberOfCells();
7110   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7111   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7112     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7113       {
7114         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7115         types.push_back(curType);
7116         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7117       }
7118   DataArrayInt *ret=DataArrayInt::New();
7119   ret->alloc(nbOfCells,1);
7120   int *retPtr=ret->getPointer();
7121   std::fill(retPtr,retPtr+nbOfCells,-1);
7122   int newCellId=0;
7123   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7124     {
7125       for(const int *i=connI;i!=connI+nbOfCells;i++)
7126         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7127           retPtr[std::distance(connI,i)]=newCellId++;
7128     }
7129   renumberCells(retPtr,false);
7130   return ret;
7131 }
7132
7133 /*!
7134  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7135  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7136  * This method makes asumption that connectivity is correctly set before calling.
7137  */
7138 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7139 {
7140   checkConnectivityFullyDefined();
7141   const int *conn=_nodal_connec->getConstPointer();
7142   const int *connI=_nodal_connec_index->getConstPointer();
7143   int nbOfCells=getNumberOfCells();
7144   std::vector<MEDCouplingUMesh *> ret;
7145   for(const int *i=connI;i!=connI+nbOfCells;)
7146     {
7147       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7148       int beginCellId=(int)std::distance(connI,i);
7149       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7150       int endCellId=(int)std::distance(connI,i);
7151       int sz=endCellId-beginCellId;
7152       int *cells=new int[sz];
7153       for(int j=0;j<sz;j++)
7154         cells[j]=beginCellId+j;
7155       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7156       delete [] cells;
7157       ret.push_back(m);
7158     }
7159   return ret;
7160 }
7161
7162 /*!
7163  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7164  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7165  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7166  *
7167  * \return a newly allocated instance, that the caller must manage.
7168  * \throw If \a this contains more than one geometric type.
7169  * \throw If the nodal connectivity of \a this is not fully defined.
7170  * \throw If the internal data is not coherent.
7171  */
7172 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7173 {
7174   checkConnectivityFullyDefined();
7175   if(_types.size()!=1)
7176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7177   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7178   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7179   ret->setCoords(getCoords());
7180   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7181   if(retC)
7182     {
7183       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7184       retC->setNodalConnectivity(c);
7185     }
7186   else
7187     {
7188       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7189       if(!retD)
7190         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7191       DataArrayInt *c=0,*ci=0;
7192       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7193       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7194       retD->setNodalConnectivity(cs,cis);
7195     }
7196   return ret.retn();
7197 }
7198
7199 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7200 {
7201   checkConnectivityFullyDefined();
7202   if(_types.size()!=1)
7203     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7204   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7205   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7206   if(cm.isDynamic())
7207     {
7208       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7209       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7210       throw INTERP_KERNEL::Exception(oss.str().c_str());
7211     }
7212   int nbCells=getNumberOfCells();
7213   int typi=(int)typ;
7214   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7216   int *outPtr=connOut->getPointer();
7217   const int *conn=_nodal_connec->begin();
7218   const int *connI=_nodal_connec_index->begin();
7219   nbNodesPerCell++;
7220   for(int i=0;i<nbCells;i++,connI++)
7221     {
7222       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7223         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7224       else
7225         {
7226           std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
7227           throw INTERP_KERNEL::Exception(oss.str().c_str());
7228         }
7229     }
7230   return connOut.retn();
7231 }
7232
7233 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7234 {
7235   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7236   checkConnectivityFullyDefined();
7237   if(_types.size()!=1)
7238     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7239   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7240   if(lgth<nbCells)
7241     throw INTERP_KERNEL::Exception(msg0);
7242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7243   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7244   int *cp(c->getPointer()),*cip(ci->getPointer());
7245   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7246   cip[0]=0;
7247   for(int i=0;i<nbCells;i++,cip++,incip++)
7248     {
7249       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7250       int delta(stop-strt);
7251       if(delta>=1)
7252         {
7253           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7254             cp=std::copy(incp+strt,incp+stop,cp);
7255           else
7256             throw INTERP_KERNEL::Exception(msg0);
7257         }
7258       else
7259         throw INTERP_KERNEL::Exception(msg0);
7260       cip[1]=cip[0]+delta;
7261     }
7262   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7263 }
7264
7265 /*!
7266  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7267  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7268  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7269  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7270  * are not used here to avoid the build of big permutation array.
7271  *
7272  * \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
7273  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7274  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7275  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7276  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7277  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7278  * \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
7279  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7280  */
7281 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7282                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7283                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7284 {
7285   std::vector<const MEDCouplingUMesh *> ms2;
7286   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7287     if(*it)
7288       {
7289         (*it)->checkConnectivityFullyDefined();
7290         ms2.push_back(*it);
7291       }
7292   if(ms2.empty())
7293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7294   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7295   int meshDim=ms2[0]->getMeshDimension();
7296   std::vector<const MEDCouplingUMesh *> m1ssm;
7297   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7298   //
7299   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7300   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7301   int fake=0,rk=0;
7302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7303   ret1->alloc(0,1); ret2->alloc(0,1);
7304   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7305     {
7306       if(meshDim!=(*it)->getMeshDimension())
7307         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7308       if(refCoo!=(*it)->getCoords())
7309         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7310       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7311       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7312       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7313       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7314         {
7315           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7316           m1ssmSingleAuto.push_back(singleCell);
7317           m1ssmSingle.push_back(singleCell);
7318           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7319         }
7320     }
7321   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7323   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7324   for(std::size_t i=0;i<m1ssm.size();i++)
7325     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7327   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7328   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7329   return ret0.retn();
7330 }
7331
7332 /*!
7333  * This method returns a newly created DataArrayInt instance.
7334  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7335  */
7336 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7337 {
7338   checkFullyDefined();
7339   const int *conn=_nodal_connec->getConstPointer();
7340   const int *connIndex=_nodal_connec_index->getConstPointer();
7341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7342   for(const int *w=begin;w!=end;w++)
7343     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7344       ret->pushBackSilent(*w);
7345   return ret.retn();
7346 }
7347
7348 /*!
7349  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7350  * are in [0:getNumberOfCells())
7351  */
7352 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7353 {
7354   checkFullyDefined();
7355   const int *conn=_nodal_connec->getConstPointer();
7356   const int *connI=_nodal_connec_index->getConstPointer();
7357   int nbOfCells=getNumberOfCells();
7358   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7359   int *tmp=new int[nbOfCells];
7360   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7361     {
7362       int j=0;
7363       for(const int *i=connI;i!=connI+nbOfCells;i++)
7364         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7365           tmp[std::distance(connI,i)]=j++;
7366     }
7367   DataArrayInt *ret=DataArrayInt::New();
7368   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7369   ret->copyStringInfoFrom(*da);
7370   int *retPtr=ret->getPointer();
7371   const int *daPtr=da->getConstPointer();
7372   int nbOfElems=da->getNbOfElems();
7373   for(int k=0;k<nbOfElems;k++)
7374     retPtr[k]=tmp[daPtr[k]];
7375   delete [] tmp;
7376   return ret;
7377 }
7378
7379 /*!
7380  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7381  * This method \b works \b for mesh sorted by type.
7382  * cells whose ids is in 'idsPerGeoType' array.
7383  * This method conserves coords and name of mesh.
7384  */
7385 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7386 {
7387   std::vector<int> code=getDistributionOfTypes();
7388   std::size_t nOfTypesInThis=code.size()/3;
7389   int sz=0,szOfType=0;
7390   for(std::size_t i=0;i<nOfTypesInThis;i++)
7391     {
7392       if(code[3*i]!=type)
7393         sz+=code[3*i+1];
7394       else
7395         szOfType=code[3*i+1];
7396     }
7397   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7398     if(*work<0 || *work>=szOfType)
7399       {
7400         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7401         oss << ". It should be in [0," << szOfType << ") !";
7402         throw INTERP_KERNEL::Exception(oss.str().c_str());
7403       }
7404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7405   int *idsPtr=idsTokeep->getPointer();
7406   int offset=0;
7407   for(std::size_t i=0;i<nOfTypesInThis;i++)
7408     {
7409       if(code[3*i]!=type)
7410         for(int j=0;j<code[3*i+1];j++)
7411           *idsPtr++=offset+j;
7412       else
7413         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7414       offset+=code[3*i+1];
7415     }
7416   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7417   ret->copyTinyInfoFrom(this);
7418   return ret.retn();
7419 }
7420
7421 /*!
7422  * This method returns a vector of size 'this->getNumberOfCells()'.
7423  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7424  */
7425 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7426 {
7427   int ncell=getNumberOfCells();
7428   std::vector<bool> ret(ncell);
7429   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7430   const int *c=getNodalConnectivity()->getConstPointer();
7431   for(int i=0;i<ncell;i++)
7432     {
7433       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7434       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7435       ret[i]=cm.isQuadratic();
7436     }
7437   return ret;
7438 }
7439
7440 /*!
7441  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7442  */
7443 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7444 {
7445   if(other->getType()!=UNSTRUCTURED)
7446     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7447   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7448   return MergeUMeshes(this,otherC);
7449 }
7450
7451 /*!
7452  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7453  * computed by averaging coordinates of cell nodes, so this method is not a right
7454  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7455  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7456  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7457  *          components. The caller is to delete this array using decrRef() as it is
7458  *          no more needed.
7459  *  \throw If the coordinates array is not set.
7460  *  \throw If the nodal connectivity of cells is not defined.
7461  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7462  */
7463 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7464 {
7465   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7466   int spaceDim=getSpaceDimension();
7467   int nbOfCells=getNumberOfCells();
7468   ret->alloc(nbOfCells,spaceDim);
7469   ret->copyStringInfoFrom(*getCoords());
7470   double *ptToFill=ret->getPointer();
7471   const int *nodal=_nodal_connec->getConstPointer();
7472   const int *nodalI=_nodal_connec_index->getConstPointer();
7473   const double *coor=_coords->getConstPointer();
7474   for(int i=0;i<nbOfCells;i++)
7475     {
7476       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7477       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7478       ptToFill+=spaceDim;
7479     }
7480   return ret.retn();
7481 }
7482
7483 /*!
7484  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7485  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7486  * 
7487  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7488  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7489  * 
7490  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7491  * \throw If \a this is not fully defined (coordinates and connectivity)
7492  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7493  */
7494 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7495 {
7496   checkFullyDefined();
7497   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7498   int spaceDim=getSpaceDimension();
7499   int nbOfCells=getNumberOfCells();
7500   int nbOfNodes=getNumberOfNodes();
7501   ret->alloc(nbOfCells,spaceDim);
7502   double *ptToFill=ret->getPointer();
7503   const int *nodal=_nodal_connec->getConstPointer();
7504   const int *nodalI=_nodal_connec_index->getConstPointer();
7505   const double *coor=_coords->getConstPointer();
7506   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7507     {
7508       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7509       std::fill(ptToFill,ptToFill+spaceDim,0.);
7510       if(type!=INTERP_KERNEL::NORM_POLYHED)
7511         {
7512           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7513             {
7514               if(*conn>=0 && *conn<nbOfNodes)
7515                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7516               else
7517                 {
7518                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7519                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7520                 }
7521             }
7522           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7523           if(nbOfNodesInCell>0)
7524             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7525           else
7526             {
7527               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7528               throw INTERP_KERNEL::Exception(oss.str().c_str());
7529             }
7530         }
7531       else
7532         {
7533           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7534           s.erase(-1);
7535           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7536             {
7537               if(*it>=0 && *it<nbOfNodes)
7538                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7539               else
7540                 {
7541                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7542                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7543                 }
7544             }
7545           if(!s.empty())
7546             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7547           else
7548             {
7549               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7550               throw INTERP_KERNEL::Exception(oss.str().c_str());
7551             }
7552         }
7553     }
7554   return ret.retn();
7555 }
7556
7557 /*!
7558  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7559  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7560  * are specified via an array of cell ids. 
7561  *  \warning Validity of the specified cell ids is not checked! 
7562  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7563  *  \param [in] begin - an array of cell ids of interest.
7564  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7565  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7566  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7567  *          caller is to delete this array using decrRef() as it is no more needed. 
7568  *  \throw If the coordinates array is not set.
7569  *  \throw If the nodal connectivity of cells is not defined.
7570  *
7571  *  \if ENABLE_EXAMPLES
7572  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7573  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7574  *  \endif
7575  */
7576 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7577 {
7578   DataArrayDouble *ret=DataArrayDouble::New();
7579   int spaceDim=getSpaceDimension();
7580   int nbOfTuple=(int)std::distance(begin,end);
7581   ret->alloc(nbOfTuple,spaceDim);
7582   double *ptToFill=ret->getPointer();
7583   double *tmp=new double[spaceDim];
7584   const int *nodal=_nodal_connec->getConstPointer();
7585   const int *nodalI=_nodal_connec_index->getConstPointer();
7586   const double *coor=_coords->getConstPointer();
7587   for(const int *w=begin;w!=end;w++)
7588     {
7589       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7590       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7591       ptToFill+=spaceDim;
7592     }
7593   delete [] tmp;
7594   return ret;
7595 }
7596
7597 /*!
7598  * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7599  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7600  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7601  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7602  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7603  * 
7604  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7605  * \throw If spaceDim!=3 or meshDim!=2.
7606  * \throw If connectivity of \a this is invalid.
7607  * \throw If connectivity of a cell in \a this points to an invalid node.
7608  */
7609 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7610 {
7611   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7612   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7613   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7614     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7615   ret->alloc(nbOfCells,4);
7616   double *retPtr(ret->getPointer());
7617   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7618   const double *coor(_coords->begin());
7619   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7620     {
7621       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7622       if(nodalI[1]-nodalI[0]>=3)
7623         {
7624           for(int j=0;j<3;j++)
7625             {
7626               int nodeId(nodal[nodalI[0]+1+j]);
7627               if(nodeId>=0 && nodeId<nbOfNodes)
7628                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7629               else
7630                 {
7631                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7632                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7633                 }
7634             }
7635         }
7636       else
7637         {
7638           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7639           throw INTERP_KERNEL::Exception(oss.str().c_str());
7640         }
7641       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7642       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7643     }
7644   return ret.retn();
7645 }
7646
7647 /*!
7648  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7649  * 
7650  */
7651 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7652 {
7653   if(!da)
7654     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7655   da->checkAllocated();
7656   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7657   ret->setCoords(da);
7658   int nbOfTuples=da->getNumberOfTuples();
7659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7661   c->alloc(2*nbOfTuples,1);
7662   cI->alloc(nbOfTuples+1,1);
7663   int *cp=c->getPointer();
7664   int *cip=cI->getPointer();
7665   *cip++=0;
7666   for(int i=0;i<nbOfTuples;i++)
7667     {
7668       *cp++=INTERP_KERNEL::NORM_POINT1;
7669       *cp++=i;
7670       *cip++=2*(i+1);
7671     }
7672   ret->setConnectivity(c,cI,true);
7673   return ret.retn();
7674 }
7675 /*!
7676  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7677  * Cells and nodes of
7678  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7679  *  \param [in] mesh1 - the first mesh.
7680  *  \param [in] mesh2 - the second mesh.
7681  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7682  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7683  *          is no more needed.
7684  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7685  *  \throw If the coordinates array is not set in none of the meshes.
7686  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7687  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7688  */
7689 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7690 {
7691   std::vector<const MEDCouplingUMesh *> tmp(2);
7692   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7693   return MergeUMeshes(tmp);
7694 }
7695
7696 /*!
7697  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7698  * Cells and nodes of
7699  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7700  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7701  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7702  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7703  *          is no more needed.
7704  *  \throw If \a a.size() == 0.
7705  *  \throw If \a a[ *i* ] == NULL.
7706  *  \throw If the coordinates array is not set in none of the meshes.
7707  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7708  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7709  */
7710 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7711 {
7712   std::size_t sz=a.size();
7713   if(sz==0)
7714     return MergeUMeshesLL(a);
7715   for(std::size_t ii=0;ii<sz;ii++)
7716     if(!a[ii])
7717       {
7718         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7719         throw INTERP_KERNEL::Exception(oss.str().c_str());
7720       }
7721   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7722   std::vector< const MEDCouplingUMesh * > aa(sz);
7723   int spaceDim=-3;
7724   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7725     {
7726       const MEDCouplingUMesh *cur=a[i];
7727       const DataArrayDouble *coo=cur->getCoords();
7728       if(coo)
7729         spaceDim=coo->getNumberOfComponents();
7730     }
7731   if(spaceDim==-3)
7732     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7733   for(std::size_t i=0;i<sz;i++)
7734     {
7735       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7736       aa[i]=bb[i];
7737     }
7738   return MergeUMeshesLL(aa);
7739 }
7740
7741 /// @cond INTERNAL
7742
7743 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7744 {
7745   if(a.empty())
7746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7747   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7748   int meshDim=(*it)->getMeshDimension();
7749   int nbOfCells=(*it)->getNumberOfCells();
7750   int meshLgth=(*it++)->getMeshLength();
7751   for(;it!=a.end();it++)
7752     {
7753       if(meshDim!=(*it)->getMeshDimension())
7754         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7755       nbOfCells+=(*it)->getNumberOfCells();
7756       meshLgth+=(*it)->getMeshLength();
7757     }
7758   std::vector<const MEDCouplingPointSet *> aps(a.size());
7759   std::copy(a.begin(),a.end(),aps.begin());
7760   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7761   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7762   ret->setCoords(pts);
7763   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7764   c->alloc(meshLgth,1);
7765   int *cPtr=c->getPointer();
7766   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7767   cI->alloc(nbOfCells+1,1);
7768   int *cIPtr=cI->getPointer();
7769   *cIPtr++=0;
7770   int offset=0;
7771   int offset2=0;
7772   for(it=a.begin();it!=a.end();it++)
7773     {
7774       int curNbOfCell=(*it)->getNumberOfCells();
7775       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7776       const int *curC=(*it)->_nodal_connec->getConstPointer();
7777       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7778       for(int j=0;j<curNbOfCell;j++)
7779         {
7780           const int *src=curC+curCI[j];
7781           *cPtr++=*src++;
7782           for(;src!=curC+curCI[j+1];src++,cPtr++)
7783             {
7784               if(*src!=-1)
7785                 *cPtr=*src+offset2;
7786               else
7787                 *cPtr=-1;
7788             }
7789         }
7790       offset+=curCI[curNbOfCell];
7791       offset2+=(*it)->getNumberOfNodes();
7792     }
7793   //
7794   ret->setConnectivity(c,cI,true);
7795   return ret.retn();
7796 }
7797
7798 /// @endcond
7799
7800 /*!
7801  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7802  * dimension and sharing the node coordinates array.
7803  * All cells of the first mesh precede all cells of the second mesh
7804  * within the result mesh. 
7805  *  \param [in] mesh1 - the first mesh.
7806  *  \param [in] mesh2 - the second mesh.
7807  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7808  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7809  *          is no more needed.
7810  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7811  *  \throw If the meshes do not share the node coordinates array.
7812  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7813  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7814  */
7815 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7816 {
7817   std::vector<const MEDCouplingUMesh *> tmp(2);
7818   tmp[0]=mesh1; tmp[1]=mesh2;
7819   return MergeUMeshesOnSameCoords(tmp);
7820 }
7821
7822 /*!
7823  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7824  * dimension and sharing the node coordinates array.
7825  * All cells of the *i*-th mesh precede all cells of the
7826  * (*i*+1)-th mesh within the result mesh.
7827  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7828  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7829  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7830  *          is no more needed.
7831  *  \throw If \a a.size() == 0.
7832  *  \throw If \a a[ *i* ] == NULL.
7833  *  \throw If the meshes do not share the node coordinates array.
7834  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7835  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7836  */
7837 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7838 {
7839   if(meshes.empty())
7840     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7841   for(std::size_t ii=0;ii<meshes.size();ii++)
7842     if(!meshes[ii])
7843       {
7844         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7845         throw INTERP_KERNEL::Exception(oss.str().c_str());
7846       }
7847   const DataArrayDouble *coords=meshes.front()->getCoords();
7848   int meshDim=meshes.front()->getMeshDimension();
7849   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7850   int meshLgth=0;
7851   int meshIndexLgth=0;
7852   for(;iter!=meshes.end();iter++)
7853     {
7854       if(coords!=(*iter)->getCoords())
7855         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7856       if(meshDim!=(*iter)->getMeshDimension())
7857         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7858       meshLgth+=(*iter)->getMeshLength();
7859       meshIndexLgth+=(*iter)->getNumberOfCells();
7860     }
7861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7862   nodal->alloc(meshLgth,1);
7863   int *nodalPtr=nodal->getPointer();
7864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7865   nodalIndex->alloc(meshIndexLgth+1,1);
7866   int *nodalIndexPtr=nodalIndex->getPointer();
7867   int offset=0;
7868   for(iter=meshes.begin();iter!=meshes.end();iter++)
7869     {
7870       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7871       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7872       int nbOfCells=(*iter)->getNumberOfCells();
7873       int meshLgth2=(*iter)->getMeshLength();
7874       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7875       if(iter!=meshes.begin())
7876         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7877       else
7878         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7879       offset+=meshLgth2;
7880     }
7881   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7882   ret->setName("merge");
7883   ret->setMeshDimension(meshDim);
7884   ret->setConnectivity(nodal,nodalIndex,true);
7885   ret->setCoords(coords);
7886   return ret;
7887 }
7888
7889 /*!
7890  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7891  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7892  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7893  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7894  * New" mode are returned for each input mesh.
7895  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7896  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7897  *          valid values [0,1,2], see zipConnectivityTraducer().
7898  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7899  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7900  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7901  *          no more needed.
7902  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7903  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7904  *          is no more needed.
7905  *  \throw If \a meshes.size() == 0.
7906  *  \throw If \a meshes[ *i* ] == NULL.
7907  *  \throw If the meshes do not share the node coordinates array.
7908  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7909  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7910  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7911  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7912  */
7913 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7914 {
7915   //All checks are delegated to MergeUMeshesOnSameCoords
7916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7917   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7918   corr.resize(meshes.size());
7919   std::size_t nbOfMeshes=meshes.size();
7920   int offset=0;
7921   const int *o2nPtr=o2n->getConstPointer();
7922   for(std::size_t i=0;i<nbOfMeshes;i++)
7923     {
7924       DataArrayInt *tmp=DataArrayInt::New();
7925       int curNbOfCells=meshes[i]->getNumberOfCells();
7926       tmp->alloc(curNbOfCells,1);
7927       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7928       offset+=curNbOfCells;
7929       tmp->setName(meshes[i]->getName());
7930       corr[i]=tmp;
7931     }
7932   return ret.retn();
7933 }
7934
7935 /*!
7936  * Makes all given meshes share the nodal connectivity array. The common connectivity
7937  * array is created by concatenating the connectivity arrays of all given meshes. All
7938  * the given meshes must be of the same space dimension but dimension of cells **can
7939  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7940  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7941  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7942  *  \param [in,out] meshes - a vector of meshes to update.
7943  *  \throw If any of \a meshes is NULL.
7944  *  \throw If the coordinates array is not set in any of \a meshes.
7945  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7946  *  \throw If \a meshes are of different space dimension.
7947  */
7948 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7949 {
7950   std::size_t sz=meshes.size();
7951   if(sz==0 || sz==1)
7952     return;
7953   std::vector< const DataArrayDouble * > coords(meshes.size());
7954   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7955   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7956     {
7957       if((*it))
7958         {
7959           (*it)->checkConnectivityFullyDefined();
7960           const DataArrayDouble *coo=(*it)->getCoords();
7961           if(coo)
7962             *it2=coo;
7963           else
7964             {
7965               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7966               oss << " has no coordinate array defined !";
7967               throw INTERP_KERNEL::Exception(oss.str().c_str());
7968             }
7969         }
7970       else
7971         {
7972           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7973           oss << " is null !";
7974           throw INTERP_KERNEL::Exception(oss.str().c_str());
7975         }
7976     }
7977   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7978   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7979   int offset=(*it)->getNumberOfNodes();
7980   (*it++)->setCoords(res);
7981   for(;it!=meshes.end();it++)
7982     {
7983       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7984       (*it)->setCoords(res);
7985       (*it)->shiftNodeNumbersInConn(offset);
7986       offset+=oldNumberOfNodes;
7987     }
7988 }
7989
7990 /*!
7991  * Merges nodes coincident with a given precision within all given meshes that share
7992  * the nodal connectivity array. The given meshes **can be of different** mesh
7993  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7994  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7995  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7996  *  \param [in,out] meshes - a vector of meshes to update.
7997  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7998  *  \throw If any of \a meshes is NULL.
7999  *  \throw If the \a meshes do not share the same node coordinates array.
8000  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8001  */
8002 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8003 {
8004   if(meshes.empty())
8005     return ;
8006   std::set<const DataArrayDouble *> s;
8007   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8008     {
8009       if(*it)
8010         s.insert((*it)->getCoords());
8011       else
8012         {
8013           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 !";
8014           throw INTERP_KERNEL::Exception(oss.str().c_str());
8015         }
8016     }
8017   if(s.size()!=1)
8018     {
8019       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 !";
8020       throw INTERP_KERNEL::Exception(oss.str().c_str());
8021     }
8022   const DataArrayDouble *coo=*(s.begin());
8023   if(!coo)
8024     return;
8025   //
8026   DataArrayInt *comm,*commI;
8027   coo->findCommonTuples(eps,-1,comm,commI);
8028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8029   int oldNbOfNodes=coo->getNumberOfTuples();
8030   int newNbOfNodes;
8031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8032   if(oldNbOfNodes==newNbOfNodes)
8033     return ;
8034   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8035   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8036     {
8037       (*it)->renumberNodesInConn(o2n->getConstPointer());
8038       (*it)->setCoords(newCoords);
8039     } 
8040 }
8041
8042 /*!
8043  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
8044  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8045  * \param isQuad specifies the policy of connectivity.
8046  * @ret in/out parameter in which the result will be append
8047  */
8048 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8049 {
8050   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8051   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8052   ret.push_back(cm.getExtrudedType());
8053   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8054   switch(flatType)
8055   {
8056     case INTERP_KERNEL::NORM_POINT1:
8057       {
8058         ret.push_back(connBg[1]);
8059         ret.push_back(connBg[1]+nbOfNodesPerLev);
8060         break;
8061       }
8062     case INTERP_KERNEL::NORM_SEG2:
8063       {
8064         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8065         ret.insert(ret.end(),conn,conn+4);
8066         break;
8067       }
8068     case INTERP_KERNEL::NORM_SEG3:
8069       {
8070         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8071         ret.insert(ret.end(),conn,conn+8);
8072         break;
8073       }
8074     case INTERP_KERNEL::NORM_QUAD4:
8075       {
8076         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8077         ret.insert(ret.end(),conn,conn+8);
8078         break;
8079       }
8080     case INTERP_KERNEL::NORM_TRI3:
8081       {
8082         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8083         ret.insert(ret.end(),conn,conn+6);
8084         break;
8085       }
8086     case INTERP_KERNEL::NORM_TRI6:
8087       {
8088         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,
8089           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8090         ret.insert(ret.end(),conn,conn+15);
8091         break;
8092       }
8093     case INTERP_KERNEL::NORM_QUAD8:
8094       {
8095         int conn[20]={
8096           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8097           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8098           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8099         };
8100         ret.insert(ret.end(),conn,conn+20);
8101         break;
8102       }
8103     case INTERP_KERNEL::NORM_POLYGON:
8104       {
8105         std::back_insert_iterator< std::vector<int> > ii(ret);
8106         std::copy(connBg+1,connEnd,ii);
8107         *ii++=-1;
8108         std::reverse_iterator<const int *> rConnBg(connEnd);
8109         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8110         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8111         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8112         for(std::size_t i=0;i<nbOfRadFaces;i++)
8113           {
8114             *ii++=-1;
8115             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8116             std::copy(conn,conn+4,ii);
8117           }
8118         break;
8119       }
8120     default:
8121       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8122   }
8123 }
8124
8125 /*!
8126  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8127  */
8128 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8129 {
8130   std::size_t i, ip1;
8131   double v[3]={0.,0.,0.};
8132   std::size_t sz=std::distance(begin,end);
8133   if(isQuadratic)
8134     sz/=2;
8135   for(i=0;i<sz;i++)
8136     {
8137       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];
8138       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8139       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8140     }
8141   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8142
8143   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8144   // SEG3 forming a circle):
8145   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8146     {
8147       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8148       for(std::size_t j=0;j<sz;j++)
8149         {
8150           if (j%2)  // current point i is quadratic, next point i+1 is standard
8151             {
8152               i = sz+j;
8153               ip1 = (j+1)%sz; // ip1 = "i+1"
8154             }
8155           else      // current point i is standard, next point i+1 is quadratic
8156             {
8157               i = j;
8158               ip1 = j+sz;
8159             }
8160           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8161           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8162           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8163         }
8164       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8165     }
8166   return (ret>0.);
8167 }
8168
8169 /*!
8170  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8171  */
8172 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8173 {
8174   std::vector<std::pair<int,int> > edges;
8175   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8176   const int *bgFace=begin;
8177   for(std::size_t i=0;i<nbOfFaces;i++)
8178     {
8179       const int *endFace=std::find(bgFace+1,end,-1);
8180       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8181       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8182         {
8183           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8184           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8185             return false;
8186           edges.push_back(p1);
8187         }
8188       bgFace=endFace+1;
8189     }
8190   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8191 }
8192
8193 /*!
8194  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8195  */
8196 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8197 {
8198   double vec0[3],vec1[3];
8199   std::size_t sz=std::distance(begin,end);
8200   if(sz%2!=0)
8201     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8202   int nbOfNodes=(int)sz/2;
8203   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8204   const double *pt0=coords+3*begin[0];
8205   const double *pt1=coords+3*begin[nbOfNodes];
8206   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8207   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8208 }
8209
8210 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8211 {
8212   std::size_t sz=std::distance(begin,end);
8213   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8214   std::size_t nbOfNodes(sz/2);
8215   std::copy(begin,end,(int *)tmp);
8216   for(std::size_t j=1;j<nbOfNodes;j++)
8217     {
8218       begin[j]=tmp[nbOfNodes-j];
8219       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8220     }
8221 }
8222
8223 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8224 {
8225   std::size_t sz=std::distance(begin,end);
8226   if(sz!=4)
8227     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8228   double vec0[3],vec1[3];
8229   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8230   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]; 
8231   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;
8232 }
8233
8234 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8235 {
8236   std::size_t sz=std::distance(begin,end);
8237   if(sz!=5)
8238     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8239   double vec0[3];
8240   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8241   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8242   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8243 }
8244
8245 /*!
8246  * 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 ) 
8247  * 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
8248  * a 2D space.
8249  *
8250  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8251  * \param [in] coords the coordinates with nb of components exactly equal to 3
8252  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8253  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8254  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8255  */
8256 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8257 {
8258   int nbFaces=std::count(begin+1,end,-1)+1;
8259   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8260   double *vPtr=v->getPointer();
8261   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8262   double *pPtr=p->getPointer();
8263   const int *stFaceConn=begin+1;
8264   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8265     {
8266       const int *endFaceConn=std::find(stFaceConn,end,-1);
8267       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8268       stFaceConn=endFaceConn+1;
8269     }
8270   pPtr=p->getPointer(); vPtr=v->getPointer();
8271   DataArrayInt *comm1=0,*commI1=0;
8272   v->findCommonTuples(eps,-1,comm1,commI1);
8273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8274   const int *comm1Ptr=comm1->getConstPointer();
8275   const int *commI1Ptr=commI1->getConstPointer();
8276   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8277   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8278   //
8279   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8280   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8281   mm->finishInsertingCells();
8282   //
8283   for(int i=0;i<nbOfGrps1;i++)
8284     {
8285       int vecId=comm1Ptr[commI1Ptr[i]];
8286       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8287       DataArrayInt *comm2=0,*commI2=0;
8288       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8289       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8290       const int *comm2Ptr=comm2->getConstPointer();
8291       const int *commI2Ptr=commI2->getConstPointer();
8292       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8293       for(int j=0;j<nbOfGrps2;j++)
8294         {
8295           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8296             {
8297               res->insertAtTheEnd(begin,end);
8298               res->pushBackSilent(-1);
8299             }
8300           else
8301             {
8302               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8303               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8304               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8305               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8306               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8307               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8308               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8309               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8310               const int *idsNodePtr=idsNode->getConstPointer();
8311               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];
8312               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8313               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8314               if(std::abs(norm)>eps)
8315                 {
8316                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8317                   mm3->rotate(center,vec,angle);
8318                 }
8319               mm3->changeSpaceDimension(2);
8320               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8321               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8322               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8323               int nbOfCells=mm4->getNumberOfCells();
8324               for(int k=0;k<nbOfCells;k++)
8325                 {
8326                   int l=0;
8327                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8328                     res->pushBackSilent(idsNodePtr[*work]);
8329                   res->pushBackSilent(-1);
8330                 }
8331             }
8332         }
8333     }
8334   res->popBackSilent();
8335 }
8336
8337 /*!
8338  * 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
8339  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8340  * 
8341  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8342  * \param [in] coords coordinates expected to have 3 components.
8343  * \param [in] begin start of the nodal connectivity of the face.
8344  * \param [in] end end of the nodal connectivity (excluded) of the face.
8345  * \param [out] v the normalized vector of size 3
8346  * \param [out] p the pos of plane
8347  */
8348 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8349 {
8350   std::size_t nbPoints=std::distance(begin,end);
8351   if(nbPoints<3)
8352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8353   double vec[3]={0.,0.,0.};
8354   std::size_t j=0;
8355   bool refFound=false;
8356   for(;j<nbPoints-1 && !refFound;j++)
8357     {
8358       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8359       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8360       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8361       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8362       if(norm>eps)
8363         {
8364           refFound=true;
8365           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8366         }
8367     }
8368   for(std::size_t i=j;i<nbPoints-1;i++)
8369     {
8370       double curVec[3];
8371       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8372       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8373       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8374       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8375       if(norm<eps)
8376         continue;
8377       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8378       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];
8379       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8380       if(norm>eps)
8381         {
8382           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8383           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8384           return ;
8385         }
8386     }
8387   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8388 }
8389
8390 /*!
8391  * This method tries to obtain a well oriented polyhedron.
8392  * If the algorithm fails, an exception will be thrown.
8393  */
8394 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8395 {
8396   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8397   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8398   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8399   isPerm[0]=true;
8400   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8401   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8402   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8403   //
8404   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8405     {
8406       bgFace=begin;
8407       std::size_t smthChanged=0;
8408       for(std::size_t i=0;i<nbOfFaces;i++)
8409         {
8410           endFace=std::find(bgFace+1,end,-1);
8411           nbOfEdgesInFace=std::distance(bgFace,endFace);
8412           if(!isPerm[i])
8413             {
8414               bool b;
8415               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8416                 {
8417                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8418                   std::pair<int,int> p2(p1.second,p1.first);
8419                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8420                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8421                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8422                 }
8423               if(isPerm[i])
8424                 { 
8425                   if(!b)
8426                     std::reverse(bgFace+1,endFace);
8427                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8428                     {
8429                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8430                       std::pair<int,int> p2(p1.second,p1.first);
8431                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8432                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8433                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8434                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8435                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8436                       if(it!=edgesOK.end())
8437                         {
8438                           edgesOK.erase(it);
8439                           edgesFinished.push_back(p1);
8440                         }
8441                       else
8442                         edgesOK.push_back(p1);
8443                     }
8444                 }
8445             }
8446           bgFace=endFace+1;
8447         }
8448       if(smthChanged==0)
8449         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8450     }
8451   if(!edgesOK.empty())
8452     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8453   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8454     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8455       bgFace=begin;
8456       for(std::size_t i=0;i<nbOfFaces;i++)
8457         {
8458           endFace=std::find(bgFace+1,end,-1);
8459           std::reverse(bgFace+1,endFace);
8460           bgFace=endFace+1;
8461         }
8462     }
8463 }
8464
8465 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8466 {
8467   int nbOfNodesExpected(skin->getNumberOfNodes());
8468   const int *n2oPtr(n2o->getConstPointer());
8469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8470   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8471   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8472   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8473   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8474   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8475   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8476   if(nbOfNodesExpected<1)
8477     return ret.retn();
8478   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8479   *work++=n2oPtr[prevNode];
8480   for(int i=1;i<nbOfNodesExpected;i++)
8481     {
8482       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8483         {
8484           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8485           conn.erase(prevNode);
8486           if(conn.size()==1)
8487             {
8488               int curNode(*(conn.begin()));
8489               *work++=n2oPtr[curNode];
8490               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8491               shar.erase(prevCell);
8492               if(shar.size()==1)
8493                 {
8494                   prevCell=*(shar.begin());
8495                   prevNode=curNode;
8496                 }
8497               else
8498                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8499             }
8500           else
8501             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8502         }
8503       else
8504         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8505     }
8506   return ret.retn();
8507 }
8508
8509 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8510 {
8511   int nbOfNodesExpected(skin->getNumberOfNodes());
8512   int nbOfTurn(nbOfNodesExpected/2);
8513   const int *n2oPtr(n2o->getConstPointer());
8514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8515   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8516   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8517   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8518   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8519   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8520   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8521   if(nbOfNodesExpected<1)
8522     return ret.retn();
8523   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8524   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8525   for(int i=1;i<nbOfTurn;i++)
8526     {
8527       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8528         {
8529           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8530           conn.erase(prevNode);
8531           if(conn.size()==1)
8532             {
8533               int curNode(*(conn.begin()));
8534               *work=n2oPtr[curNode];
8535               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8536               shar.erase(prevCell);
8537               if(shar.size()==1)
8538                 {
8539                   int curCell(*(shar.begin()));
8540                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8541                   prevCell=curCell;
8542                   prevNode=curNode;
8543                   work++;
8544                 }
8545               else
8546                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8547             }
8548           else
8549             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8550         }
8551       else
8552         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8553     }
8554   return ret.retn();
8555 }
8556
8557 /*!
8558  * This method makes the assumption spacedimension == meshdimension == 2.
8559  * This method works only for linear cells.
8560  * 
8561  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8562  */
8563 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8564 {
8565   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8566     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8567   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8568   int oldNbOfNodes(skin->getNumberOfNodes());
8569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8570   int nbOfNodesExpected(skin->getNumberOfNodes());
8571   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8572   int nbCells(skin->getNumberOfCells());
8573   if(nbCells==nbOfNodesExpected)
8574     return buildUnionOf2DMeshLinear(skin,n2o);
8575   else if(2*nbCells==nbOfNodesExpected)
8576     return buildUnionOf2DMeshQuadratic(skin,n2o);
8577   else
8578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8579 }
8580
8581 /*!
8582  * This method makes the assumption spacedimension == meshdimension == 3.
8583  * This method works only for linear cells.
8584  * 
8585  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8586  */
8587 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8588 {
8589   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8590     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8591   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8592   const int *conn=m->getNodalConnectivity()->getConstPointer();
8593   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8594   int nbOfCells=m->getNumberOfCells();
8595   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8596   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8597   if(nbOfCells<1)
8598     return ret.retn();
8599   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8600   for(int i=1;i<nbOfCells;i++)
8601     {
8602       *work++=-1;
8603       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8604     }
8605   return ret.retn();
8606 }
8607
8608 /*!
8609  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8610  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8611  */
8612 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8613 {
8614   double *w=zipFrmt;
8615   if(spaceDim==3)
8616     for(int i=0;i<nbOfNodesInCell;i++)
8617       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8618   else if(spaceDim==2)
8619     {
8620       for(int i=0;i<nbOfNodesInCell;i++)
8621         {
8622           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8623           *w++=0.;
8624         }
8625     }
8626   else
8627     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8628 }
8629
8630 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8631 {
8632   int nbOfCells=getNumberOfCells();
8633   if(nbOfCells<=0)
8634     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8635   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,36,4};
8636   ofs << "  <" << getVTKDataSetType() << ">\n";
8637   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8638   ofs << "      <PointData>\n" << pointData << std::endl;
8639   ofs << "      </PointData>\n";
8640   ofs << "      <CellData>\n" << cellData << std::endl;
8641   ofs << "      </CellData>\n";
8642   ofs << "      <Points>\n";
8643   if(getSpaceDimension()==3)
8644     _coords->writeVTK(ofs,8,"Points",byteData);
8645   else
8646     {
8647       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8648       coo->writeVTK(ofs,8,"Points",byteData);
8649     }
8650   ofs << "      </Points>\n";
8651   ofs << "      <Cells>\n";
8652   const int *cPtr=_nodal_connec->getConstPointer();
8653   const int *cIPtr=_nodal_connec_index->getConstPointer();
8654   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8658   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8659   int szFaceOffsets=0,szConn=0;
8660   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8661     {
8662       *w2=cPtr[cIPtr[i]];
8663       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8664         {
8665           *w1=-1;
8666           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8667           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8668         }
8669       else
8670         {
8671           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8672           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8673           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8674           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8675           w4=std::copy(c.begin(),c.end(),w4);
8676         }
8677     }
8678   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8679   types->writeVTK(ofs,8,"UInt8","types",byteData);
8680   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8681   if(szFaceOffsets!=0)
8682     {//presence of Polyhedra
8683       connectivity->reAlloc(szConn);
8684       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8685       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8686       w1=faces->getPointer();
8687       for(int i=0;i<nbOfCells;i++)
8688         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8689           {
8690             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8691             *w1++=nbFaces;
8692             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8693             for(int j=0;j<nbFaces;j++)
8694               {
8695                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8696                 *w1++=(int)std::distance(w6,w5);
8697                 w1=std::copy(w6,w5,w1);
8698                 w6=w5+1;
8699               }
8700           }
8701       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8702     }
8703   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8704   ofs << "      </Cells>\n";
8705   ofs << "    </Piece>\n";
8706   ofs << "  </" << getVTKDataSetType() << ">\n";
8707 }
8708
8709 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8710 {
8711   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8712   if(_mesh_dim==-2)
8713     { stream << " Not set !"; return ; }
8714   stream << " Mesh dimension : " << _mesh_dim << ".";
8715   if(_mesh_dim==-1)
8716     return ;
8717   if(!_coords)
8718     { stream << " No coordinates set !"; return ; }
8719   if(!_coords->isAllocated())
8720     { stream << " Coordinates set but not allocated !"; return ; }
8721   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8722   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8723   if(!_nodal_connec_index)
8724     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8725   if(!_nodal_connec_index->isAllocated())
8726     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8727   int lgth=_nodal_connec_index->getNumberOfTuples();
8728   int cpt=_nodal_connec_index->getNumberOfComponents();
8729   if(cpt!=1 || lgth<1)
8730     return ;
8731   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8732 }
8733
8734 std::string MEDCouplingUMesh::getVTKDataSetType() const
8735 {
8736   return std::string("UnstructuredGrid");
8737 }
8738
8739 std::string MEDCouplingUMesh::getVTKFileExtension() const
8740 {
8741   return std::string("vtu");
8742 }
8743
8744 /*!
8745  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8746  * returns a result mesh constituted by polygons.
8747  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8748  * all nodes from m2.
8749  * The meshes should be in 2D space. In
8750  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8751  * meshes.
8752  *  \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8753  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8754  *  \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
8755  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8756  *  \param [in] eps - precision used to detect coincident mesh entities.
8757  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8758  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8759  *         this array using decrRef() as it is no more needed.
8760  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8761  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8762  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8763  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8764  *         it is no more needed.  
8765  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8766  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8767  *         is no more needed.  
8768  *  \throw If the coordinates array is not set in any of the meshes.
8769  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8770  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8771  *
8772  *  \sa conformize2D, mergeNodes
8773  */
8774 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8775                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8776 {
8777   if(!m1 || !m2)
8778     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8779   m1->checkFullyDefined();
8780   m2->checkFullyDefined();
8781   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8783
8784   // Step 1: compute all edge intersections (new nodes)
8785   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8786   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8787   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8788   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8789   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8790                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8791                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8792   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8794   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8795
8796   // Step 2: re-order newly created nodes according to the ordering found in m2
8797   std::vector< std::vector<int> > intersectEdge2;
8798   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8799   subDiv2.clear(); dd5=0; dd6=0;
8800
8801   // Step 3:
8802   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8803   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8804   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8805                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8806
8807   // Step 4: Prepare final result:
8808   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8809   addCooDa->alloc((int)(addCoo.size())/2,2);
8810   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8811   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8812   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8813   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8814   std::vector<const DataArrayDouble *> coordss(4);
8815   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8816   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8817   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8822   ret->setConnectivity(conn,connI,true);
8823   ret->setCoords(coo);
8824   cellNb1=c1.retn(); cellNb2=c2.retn();
8825   return ret.retn();
8826 }
8827
8828 /// @cond INTERNAL
8829
8830 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8831 {
8832   if(candidates.empty())
8833     return false;
8834   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8835     {
8836       const std::vector<int>& pool(intersectEdge1[*it]);
8837       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8838       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8839         {
8840           retVal=*it+1;
8841           return true;
8842         }
8843       tmp[0]=stop; tmp[1]=start;
8844       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8845         {
8846           retVal=-*it-1;
8847           return true;
8848         }
8849     }
8850   return false;
8851 }
8852
8853 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo, const std::map<int,int>& mergedNodes, const std::vector< std::vector<int> >& colinear2, const std::vector< std::vector<int> >& intersectEdge1,
8854                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8855 {
8856   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8857   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8858   int nCells(mesh1D->getNumberOfCells());
8859   if(nCells!=(int)intersectEdge2.size())
8860     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8861   const DataArrayDouble *coo2(mesh1D->getCoords());
8862   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8863   const double *coo2Ptr(coo2->begin());
8864   int offset1(coords1->getNumberOfTuples());
8865   int offset2(offset1+coo2->getNumberOfTuples());
8866   int offset3(offset2+addCoo.size()/2);
8867   std::vector<double> addCooQuad;
8868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8869   int tmp[4],cicnt(0),kk(0);
8870   for(int i=0;i<nCells;i++)
8871     {
8872       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8873       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8874       const std::vector<int>& subEdges(intersectEdge2[i]);
8875       int nbSubEdge(subEdges.size()/2);
8876       for(int j=0;j<nbSubEdge;j++,kk++)
8877         {
8878           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
8879           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8880           INTERP_KERNEL::Edge *e2Ptr(e2);
8881           std::map<int,int>::const_iterator itm;
8882           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8883             {
8884               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8885               itm=mergedNodes.find(subEdges[2*j]);
8886               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8887               itm=mergedNodes.find(subEdges[2*j+1]);
8888               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8889               tmp[3]=offset3+(int)addCooQuad.size()/2;
8890               double tmp2[2];
8891               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8892               cicnt+=4;
8893               cOut->insertAtTheEnd(tmp,tmp+4);
8894               ciOut->pushBackSilent(cicnt);
8895             }
8896           else
8897             {
8898               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8899               itm=mergedNodes.find(subEdges[2*j]);
8900               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8901               itm=mergedNodes.find(subEdges[2*j+1]);
8902               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8903               cicnt+=3;
8904               cOut->insertAtTheEnd(tmp,tmp+3);
8905               ciOut->pushBackSilent(cicnt);
8906             }
8907           int tmp00;
8908           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8909             {
8910               idsInRetColinear->pushBackSilent(kk);
8911               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8912             }
8913         }
8914       e->decrRef();
8915     }
8916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8917   ret->setConnectivity(cOut,ciOut,true);
8918   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8919   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8920   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8921   std::vector<const DataArrayDouble *> coordss(4);
8922   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8923   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8924   ret->setCoords(arr);
8925   return ret.retn();
8926 }
8927
8928 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
8929 {
8930   std::vector<int> allEdges;
8931   for(const int *it2(descBg);it2!=descEnd;it2++)
8932     {
8933       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
8934       if(*it2>0)
8935         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
8936       else
8937         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
8938     }
8939   std::size_t nb(allEdges.size());
8940   if(nb%2!=0)
8941     throw INTERP_KERNEL::Exception("BuildRefined2DCell : internal error 1 !");
8942   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8943   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
8944   ret->setCoords(coords);
8945   ret->allocateCells(1);
8946   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
8947   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
8948     connOut[kk]=allEdges[2*kk];
8949   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
8950   return ret.retn();
8951 }
8952
8953 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
8954 {
8955   bool isQuad(false);
8956   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
8957     {
8958       const INTERP_KERNEL::Edge *ee(*it);
8959       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
8960         isQuad=true;
8961     }
8962   if(!isQuad)
8963     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
8964   else
8965     {
8966       const double *coo(mesh2D->getCoords()->begin());
8967       std::size_t sz(conn.size());
8968       std::vector<double> addCoo;
8969       std::vector<int> conn2(conn);
8970       int offset(mesh2D->getNumberOfNodes());
8971       for(std::size_t i=0;i<sz;i++)
8972         {
8973           double tmp[2];
8974           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);
8975           addCoo.insert(addCoo.end(),tmp,tmp+2);
8976           conn2.push_back(offset+(int)i);
8977         }
8978       mesh2D->getCoords()->rearrange(1);
8979       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
8980       mesh2D->getCoords()->rearrange(2);
8981       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
8982     }
8983 }
8984
8985 /*!
8986  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
8987  */
8988 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
8989                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
8990 {
8991   std::size_t nb(edge1Bis.size()/2);
8992   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
8993   int iEnd(splitMesh1D->getNumberOfCells());
8994   if(iEnd==0)
8995     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
8996   std::size_t ii,jj;
8997   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
8998   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
8999   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9000   //
9001   if(jj==nb)
9002     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9003       out0.resize(1); out1.resize(1);
9004       std::vector<int>& connOut(out0[0]);
9005       connOut.resize(nbOfEdgesOf2DCellSplit);
9006       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9007       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9008       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9009         {
9010           connOut[kk]=edge1Bis[2*kk];
9011           edgesPtr[kk]=edge1BisPtr[2*kk];
9012         }
9013     }
9014   else
9015     {
9016       // [i,iEnd[ contains the
9017       out0.resize(2); out1.resize(2);
9018       std::vector<int>& connOutLeft(out0[0]);
9019       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9020       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9021       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9022       for(std::size_t k=ii;k<jj+1;k++)
9023         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9024       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9025       for(int ik=iEnd-1;ik>=0;ik--)
9026         {
9027           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9028           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9029           ees[iEnd-1-ik]=ee;
9030         }
9031       for(int ik=iEnd-1;ik>=0;ik--)
9032         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9033       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9034         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9035       eleft.insert(eleft.end(),ees.begin(),ees.end());
9036       for(int ik=0;ik<iEnd;ik++)
9037         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9038       eright.insert(eright.end(),ees.rbegin(),ees.rend());
9039     }
9040 }
9041
9042 /// @endcond
9043
9044 /// @cond INTERNAL
9045
9046 struct CellInfo
9047 {
9048 public:
9049   CellInfo() { }
9050   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9051 public:
9052   std::vector<int> _edges;
9053   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9054 };
9055
9056 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9057 {
9058   std::size_t nbe(edges.size());
9059   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9060   for(std::size_t i=0;i<nbe;i++)
9061     {
9062       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9063       edgesPtr2[2*i]=edgesPtr[i]; edgesPtr2[2*i+1]=edgesPtr[i];
9064     }
9065   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9066   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9067   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9068 }
9069
9070 class EdgeInfo
9071 {
9072 public:
9073   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9074   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9075   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9076   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9077   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9078 private:
9079   int _istart;
9080   int _iend;
9081   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9082   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9083   int _left;
9084   int _right;
9085 };
9086
9087 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9088 {
9089   const MEDCouplingUMesh *mesh(_mesh);
9090   if(mesh)
9091     return ;
9092   if(_right<pos)
9093     return ;
9094   if(_left>pos)
9095     { _left++; _right++; return ; }
9096   if(_right==pos)
9097     {
9098       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9099       if((isLeft && isRight) || (!isLeft && !isRight))
9100         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9101       if(isLeft)
9102         return ;
9103       if(isRight)
9104         {
9105           _right++;
9106           return ;
9107         }
9108     }
9109   if(_left==pos)
9110     {
9111       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9112       if((isLeft && isRight) || (!isLeft && !isRight))
9113         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9114       if(isLeft)
9115         {
9116           _right++;
9117           return ;
9118         }
9119       if(isRight)
9120         {
9121           _left++;
9122           _right++;
9123           return ;
9124         }
9125     }
9126 }
9127
9128 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9129 {
9130   const MEDCouplingUMesh *mesh(_mesh);
9131   if(!mesh)
9132     {
9133       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9134     }
9135   else
9136     {// not fully splitting cell case
9137       if(mesh2D->getNumberOfCells()==1)
9138         {//little optimization. 1 cell no need to find in which cell mesh is !
9139           neighbors[0]=offset; neighbors[1]=offset;
9140           return;
9141         }
9142       else
9143         {
9144           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9145           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9146           if(cellId==-1)
9147             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9148           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9149         }
9150     }
9151 }
9152
9153 class VectorOfCellInfo
9154 {
9155 public:
9156   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9157   std::size_t size() const { return _pool.size(); }
9158   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9159   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9160   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9161   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9162   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9163   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9164 private:
9165   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9166   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9167   const CellInfo& get(int pos) const;
9168   CellInfo& get(int pos);
9169 private:
9170   std::vector<CellInfo> _pool;
9171   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9172   std::vector<EdgeInfo> _edge_info;
9173 };
9174
9175 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9176 {
9177   _pool[0]._edges=edges;
9178   _pool[0]._edges_ptr=edgesPtr;
9179 }
9180
9181 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9182 {
9183   if(_pool.empty())
9184     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9185   if(_pool.size()==1)
9186     return 0;
9187   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9188   if(!zeMesh)
9189     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9190   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9191   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9192 }
9193
9194 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9195 {
9196   get(pos);//to check pos
9197   bool isFast(pos==0 && _pool.size()==1);
9198   std::size_t sz(edges.size());
9199   // dealing with edges
9200   if(sz==1)
9201     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9202   else
9203     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9204   //
9205   std::vector<CellInfo> pool(_pool.size()-1+sz);
9206   for(int i=0;i<pos;i++)
9207     pool[i]=_pool[i];
9208   for(std::size_t j=0;j<sz;j++)
9209     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9210   for(int i=pos+1;i<(int)_pool.size();i++)
9211     pool[pos+sz-1]=_pool[i];
9212   _pool=pool;
9213   //
9214   if(sz==2)
9215     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9216   //
9217   if(isFast)
9218     {
9219       _ze_mesh=mesh;
9220       return ;
9221     }
9222   //
9223   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9224   if(pos>0)
9225     {
9226       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9227       ms.push_back(elt);
9228     }
9229   ms.push_back(mesh);
9230   if(pos<_ze_mesh->getNumberOfCells()-1)
9231   {
9232     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9233     ms.push_back(elt);
9234   }
9235   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9236   for(std::size_t j=0;j<ms2.size();j++)
9237     ms2[j]=ms[j];
9238   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9239 }
9240
9241 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9242 {
9243   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9244 }
9245
9246 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9247 {
9248   if(pos<0)
9249     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9250   int ret(0);
9251   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9252     {
9253       if((*it).isInMyRange(pos))
9254         return ret;
9255     }
9256   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9257 }
9258
9259 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9260 {
9261   get(pos);//to check;
9262   if(_edge_info.empty())
9263     return ;
9264   std::size_t sz(_edge_info.size()-1);
9265   for(std::size_t i=0;i<sz;i++)
9266     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9267 }
9268
9269 const CellInfo& VectorOfCellInfo::get(int pos) const
9270 {
9271   if(pos<0 || pos>=(int)_pool.size())
9272     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9273   return _pool[pos];
9274 }
9275
9276 CellInfo& VectorOfCellInfo::get(int pos)
9277 {
9278   if(pos<0 || pos>=(int)_pool.size())
9279     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9280   return _pool[pos];
9281 }
9282
9283 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9284                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9285 {
9286   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9287   if(nbCellsInSplitMesh1D==0)
9288     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9289   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9290   std::size_t nb(allEdges.size()),jj;
9291   if(nb%2!=0)
9292     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9293   std::vector<int> edge1Bis(nb*2);
9294   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9295   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9296   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9297   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9298   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9299   //
9300   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9301   int *idsLeftRightPtr(idsLeftRight->getPointer());
9302   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9303   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9304     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9305       int iEnd(iStart);
9306       for(;iEnd<nbCellsInSplitMesh1D;)
9307         {
9308           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9309           if(jj!=nb)
9310             break;
9311           else
9312             iEnd++;
9313         }
9314       if(iEnd<nbCellsInSplitMesh1D)
9315         iEnd++;
9316       //
9317       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9318       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9319       //
9320       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9321       retTmp->setCoords(splitMesh1D->getCoords());
9322       retTmp->allocateCells();
9323
9324       std::vector< std::vector<int> > out0;
9325       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9326
9327       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9328       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9329         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9330       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9331       //
9332       iStart=iEnd;
9333     }
9334   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9335     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9336   return pool.getZeMesh().retn();
9337 }
9338
9339 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9340                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9341                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9342 {
9343   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9344   //
9345   std::vector<int> allEdges;
9346   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr;
9347   for(const int *it(descBg);it!=descEnd;it++)
9348     {
9349       int edgeId(std::abs(*it)-1);
9350       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9351       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9352       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9353       if(*it>0)
9354         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9355       else
9356         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9357       std::size_t sz(edge1.size());
9358       for(std::size_t cnt=0;cnt<sz;cnt++)
9359         allEdgesPtr.push_back(ee);
9360     }
9361   //
9362   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9363 }
9364
9365 /// @endcond
9366
9367 /*!
9368  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9369  * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9370  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9371  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9372  *
9373  * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9374  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9375  * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9376  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9377  * \param [in] eps - precision used to perform intersections and localization operations.
9378  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9379  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9380  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9381  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
9382  * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9383  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9384  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
9385  *
9386  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9387  */
9388 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9389 {
9390   if(!mesh2D || !mesh1D)
9391     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9392   mesh2D->checkFullyDefined();
9393   mesh1D->checkFullyDefined();
9394   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9395   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9396     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9397   // Step 1: compute all edge intersections (new nodes)
9398   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9399   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9400   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9401   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9402   //
9403   // Build desc connectivity
9404   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9406   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9407   std::map<int,int> mergedNodes;
9408   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9409   // use mergeNodes to fix intersectEdge1
9410   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9411     {
9412       std::size_t n((*it0).size()/2);
9413       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9414       std::map<int,int>::const_iterator it1;
9415       it1=mergedNodes.find(eltStart);
9416       if(it1!=mergedNodes.end())
9417         (*it0)[0]=(*it1).second;
9418       it1=mergedNodes.find(eltEnd);
9419       if(it1!=mergedNodes.end())
9420         (*it0)[2*n-1]=(*it1).second;
9421     }
9422   //
9423   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9424   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9425   // Step 2: re-order newly created nodes according to the ordering found in m2
9426   std::vector< std::vector<int> > intersectEdge2;
9427   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9428   subDiv2.clear();
9429   // Step 3: compute splitMesh1D
9430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9432   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9433       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9434   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(-1); ret3->rearrange(2);
9435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9436   // deal with cells in mesh2D that are not cut but only some of their edges are
9437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9438   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9439   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9440   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9441   if(!idsInDesc2DToBeRefined->empty())
9442     {
9443       DataArrayInt *out0(0),*outi0(0);
9444       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9445       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9446       out0s=out0;
9447       out0s=out0s->buildUnique();
9448       out0s->sort(true);
9449     }
9450   //
9451   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9452   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9454   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9457   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9458     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9461   if((DataArrayInt *)out0s)
9462     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9463   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9464   // OK all is ready to insert in ret2 mesh
9465   if(!untouchedCells->empty())
9466     {// the most easy part, cells in mesh2D not impacted at all
9467       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9468       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9469       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9470     }
9471   if((DataArrayInt *)out0s)
9472     {// here dealing with cells in out0s but not in cellsToBeModified
9473       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9474       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9475       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9476         {
9477           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9478         }
9479       int offset(ret2->getNumberOfTuples());
9480       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9481       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9482       partOfRet3->fillWithValue(-1); partOfRet3->rearrange(2);
9483       int kk(0),*ret3ptr(partOfRet3->getPointer());
9484       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9485         {
9486           int faceId(std::abs(*it)-1);
9487           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9488             {
9489               int tmp(fewModifiedCells->locateValue(*it2));
9490               if(tmp!=-1)
9491                 {
9492                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9493                     ret3ptr[2*kk]=tmp+offset;
9494                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9495                     ret3ptr[2*kk+1]=tmp+offset;
9496                 }
9497               else
9498                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : internal error 1 !");
9499             }
9500         }
9501       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9502     }
9503   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9504     {
9505       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9506       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9507       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9508       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9509       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9510       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9511       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9512       outMesh2DSplit.push_back(splitOfOneCell);
9513       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9514         ret2->pushBackSilent(*it);
9515     }
9516   //
9517   std::size_t nbOfMeshes(outMesh2DSplit.size());
9518   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9519   for(std::size_t i=0;i<nbOfMeshes;i++)
9520     tmp[i]=outMesh2DSplit[i];
9521   //
9522   ret1->getCoords()->setInfoOnComponents(compNames);
9523   //
9524   splitMesh1D=ret1.retn();
9525   splitMesh2D=MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp);
9526   cellIdInMesh2D=ret2.retn();
9527   cellIdInMesh1D=ret3.retn();
9528 }
9529
9530 /**
9531  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9532  * (newly created) nodes corresponding to the edge intersections.
9533  * Output params:
9534  * @param[out] cr, crI connectivity of the resulting mesh
9535  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9536  * TODO: describe input parameters
9537  */
9538 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9539                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9540                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9541                                                          const std::vector<double>& addCoords,
9542                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9543 {
9544   static const int SPACEDIM=2;
9545   const double *coo1(m1->getCoords()->getConstPointer());
9546   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9547   int offset1(m1->getNumberOfNodes());
9548   const double *coo2(m2->getCoords()->getConstPointer());
9549   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9550   int offset2(offset1+m2->getNumberOfNodes());
9551   int offset3(offset2+((int)addCoords.size())/2);
9552   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9553   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9554   // Here a BBTree on 2D-cells, not on segments:
9555   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9556   int ncell1(m1->getNumberOfCells());
9557   crI.push_back(0);
9558   for(int i=0;i<ncell1;i++)
9559     {
9560       std::vector<int> candidates2;
9561       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9562       std::map<INTERP_KERNEL::Node *,int> mapp;
9563       std::map<int,INTERP_KERNEL::Node *> mappRev;
9564       INTERP_KERNEL::QuadraticPolygon pol1;
9565       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9566       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9567       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9568       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9569       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9570       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9571           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9572       //
9573       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
9574       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9575       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9576       for(it1.first();!it1.finished();it1.next())
9577         edges1.insert(it1.current()->getPtr());
9578       //
9579       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9580       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9581       int ii=0;
9582       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9583         {
9584           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9585           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9586           // Complete mapping with elements coming from the current cell it2 in mesh2:
9587           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9588           // pol2 is the new QP in the final merged result.
9589           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9590               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9591         }
9592       ii=0;
9593       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9594         {
9595           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9596           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9597           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9598           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9599         }
9600       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9601       // by m2 but that we still want to keep in the final result.
9602       if(!edges1.empty())
9603         {
9604           try
9605           {
9606               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9607           }
9608           catch(INTERP_KERNEL::Exception& e)
9609           {
9610               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();
9611               throw INTERP_KERNEL::Exception(oss.str().c_str());
9612           }
9613         }
9614       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9615         (*it).second->decrRef();
9616     }
9617 }
9618
9619 /**
9620  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9621  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9622  * This doesn't modify the mesh.
9623  * The caller is to deal with the resulting DataArrayInt.
9624  *  \throw If the coordinate array is not set.
9625  *  \throw If the nodal connectivity of the cells is not defined.
9626  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9627  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9628  */
9629 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9630 {
9631   checkFullyDefined();
9632   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
9633     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with (meshdim, spacedim) = (1,2)!");
9634
9635   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9638   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9639   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9640   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9642   const int * dsi(_dsi->getConstPointer());
9643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9644   m_points=0;
9645   if (dsii->getNumberOfTuples())
9646     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9647
9648   int nc(getNumberOfCells());
9649   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9650   result->alloc(nc,1);
9651
9652   // set of edges not used so far
9653   std::set<int> edgeSet;
9654   for (int i=0; i<nc; edgeSet.insert(i), i++);
9655
9656   int startSeg=0;
9657   int newIdx=0;
9658   // while we have points with only one neighbor segments
9659   do
9660     {
9661       std::list<int> linePiece;
9662       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9663       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9664         {
9665           // Fill the list forward (resp. backward) from the start segment:
9666           int activeSeg = startSeg;
9667           int prevPointId = -20;
9668           int ptId;
9669           while (!edgeSet.empty())
9670             {
9671               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9672                 {
9673                   if (direction==0)
9674                     linePiece.push_back(activeSeg);
9675                   else
9676                     linePiece.push_front(activeSeg);
9677                   edgeSet.erase(activeSeg);
9678                 }
9679
9680               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9681               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9682               if (dsi[ptId] == 1) // hitting the end of the line
9683                 break;
9684               prevPointId = ptId;
9685               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9686               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9687             }
9688         }
9689       // Done, save final piece into DA:
9690       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9691       newIdx += linePiece.size();
9692
9693       // identify next valid start segment (one which is not consumed)
9694       if(!edgeSet.empty())
9695         startSeg = *(edgeSet.begin());
9696     }
9697   while (!edgeSet.empty());
9698   return result.retn();
9699 }
9700
9701 /// @cond INTERNAL
9702
9703 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9704 {
9705   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9706   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9707   if(it==m.end())
9708     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9709   int v((*it).second);
9710   if(v==forbVal0 || v==forbVal1)
9711     return ;
9712   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9713     isect.push_back(v);
9714 }
9715
9716 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9717 {
9718   int sz(c.size());
9719   if(sz<=1)
9720     return false;
9721   bool presenceOfOn(false);
9722   for(int i=0;i<sz;i++)
9723     {
9724       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9725       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9726         continue ;
9727       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9728       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9729     }
9730   return presenceOfOn;
9731 }
9732
9733 /// @endcond
9734
9735 /**
9736  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
9737  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
9738  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
9739  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
9740  *
9741  * \return int - the number of new nodes created (in most of cases 0).
9742  * 
9743  * \throw If \a this is not coherent.
9744  * \throw If \a this has not spaceDim equal to 2.
9745  * \throw If \a this has not meshDim equal to 2.
9746  * \throw If some subcells needed to be split are orphan.
9747  * \sa MEDCouplingUMesh::conformize2D
9748  */
9749 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9750 {
9751   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9752     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9753   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9754   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9755     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9756   if(midOpt==0 && midOptI==0)
9757     {
9758       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9759       return 0;
9760     }
9761   else if(midOpt!=0 && midOptI!=0)
9762     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9763   else
9764     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9765 }
9766
9767 /*!
9768  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9769  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9770  * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
9771  * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
9772  * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
9773  * 
9774  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9775  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9776  *
9777  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9778  * This method expects that all nodes in \a this are not closer than \a eps.
9779  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9780  * 
9781  * \param [in] eps the relative error to detect merged edges.
9782  * \return DataArrayInt  * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
9783  *                           that the user is expected to deal with.
9784  *
9785  * \throw If \a this is not coherent.
9786  * \throw If \a this has not spaceDim equal to 2.
9787  * \throw If \a this has not meshDim equal to 2.
9788  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9789  */
9790 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9791 {
9792   static const int SPACEDIM=2;
9793   checkCoherency();
9794   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9797   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9798   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9799   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9800   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9801   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9802   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9803   std::vector<double> addCoo;
9804   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9805   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9806   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9807   for(int i=0;i<nDescCell;i++)
9808     {
9809       std::vector<int> candidates;
9810       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9811       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9812         if(*it>i)
9813           {
9814             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9815             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9816                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9817             INTERP_KERNEL::MergePoints merge;
9818             INTERP_KERNEL::QuadraticPolygon c1,c2;
9819             e1->intersectWith(e2,merge,c1,c2);
9820             e1->decrRef(); e2->decrRef();
9821             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9822               overlapEdge[i].push_back(*it);
9823             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9824               overlapEdge[*it].push_back(i);
9825           }
9826     }
9827   // splitting done. sort intersect point in intersectEdge.
9828   std::vector< std::vector<int> > middle(nDescCell);
9829   int nbOf2DCellsToBeSplit(0);
9830   bool middleNeedsToBeUsed(false);
9831   std::vector<bool> cells2DToTreat(nDescCell,false);
9832   for(int i=0;i<nDescCell;i++)
9833     {
9834       std::vector<int>& isect(intersectEdge[i]);
9835       int sz((int)isect.size());
9836       if(sz>1)
9837         {
9838           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9839           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9840           e->sortSubNodesAbs(coords,isect);
9841           e->decrRef();
9842         }
9843       if(sz!=0)
9844         {
9845           int idx0(rdi[i]),idx1(rdi[i+1]);
9846           if(idx1-idx0!=1)
9847             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9848           if(!cells2DToTreat[rd[idx0]])
9849             {
9850               cells2DToTreat[rd[idx0]]=true;
9851               nbOf2DCellsToBeSplit++;
9852             }
9853           // try to reuse at most eventual 'middle' of SEG3
9854           std::vector<int>& mid(middle[i]);
9855           mid.resize(sz+1,-1);
9856           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9857             {
9858               middleNeedsToBeUsed=true;
9859               const std::vector<int>& candidates(overlapEdge[i]);
9860               std::vector<int> trueCandidates;
9861               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9862                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9863                   trueCandidates.push_back(*itc);
9864               int stNode(c[ci[i]+1]),endNode(isect[0]);
9865               for(int j=0;j<sz+1;j++)
9866                 {
9867                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9868                     {
9869                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9870                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9871                         { mid[j]=*itc; break; }
9872                     }
9873                   stNode=endNode;
9874                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9875                 }
9876             }
9877         }
9878     }
9879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9880   if(nbOf2DCellsToBeSplit==0)
9881     return ret.retn();
9882   //
9883   int *retPtr(ret->getPointer());
9884   for(int i=0;i<nCell;i++)
9885     if(cells2DToTreat[i])
9886       *retPtr++=i;
9887   //
9888   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9889   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9890   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9891   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9892   if(middleNeedsToBeUsed)
9893     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9894   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9895   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9896   setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
9897   setPartOfMySelf(ret->begin(),ret->end(),*modif);
9898   {
9899     bool areNodesMerged; int newNbOfNodes;
9900     if(nbOfNodesCreated!=0)
9901       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9902   }
9903   return ret.retn();
9904 }
9905
9906 /*!
9907  * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
9908  * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
9909  * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
9910  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9911  * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
9912  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9913  *
9914  * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
9915  * using new instance, idem for coordinates.
9916  *
9917  * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
9918  * 
9919  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9920  *
9921  * \throw If \a this is not coherent.
9922  * \throw If \a this has not spaceDim equal to 2.
9923  * \throw If \a this has not meshDim equal to 2.
9924  * 
9925  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9926  */
9927 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9928 {
9929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9930   checkCoherency();
9931   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9933   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9934   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9935   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9936   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9938   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9939   const double *coords(_coords->begin());
9940   int *newciptr(newci->getPointer());
9941   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9942     {
9943       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9944         ret->pushBackSilent(i);
9945       newciptr[1]=newc->getNumberOfTuples();
9946     }
9947   //
9948   if(ret->empty())
9949     return ret.retn();
9950   if(!appendedCoords->empty())
9951     {
9952       appendedCoords->rearrange(2);
9953       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9954       //non const part
9955       setCoords(newCoords);
9956     }
9957   //non const part
9958   setConnectivity(newc,newci,true);
9959   return ret.retn();
9960 }
9961
9962 /*!
9963  * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
9964  *                               So for all edge \a i in \a m1Desc \a  intersectEdge1[i] is of length 2*n where n is the number of sub edges.
9965  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9966  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9967  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9968  * \param [out] addCoo - nodes to be append at the end
9969  * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc.
9970  */
9971 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9972                                          std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
9973 {
9974   static const int SPACEDIM=2;
9975   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9976   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9977   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
9978   // Build BB tree of all edges in the tool mesh (second mesh)
9979   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9980   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9981   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
9982   intersectEdge1.resize(nDescCell1);
9983   colinear2.resize(nDescCell2);
9984   subDiv2.resize(nDescCell2);
9985   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9986
9987   std::vector<int> candidates1(1);
9988   int offset1(m1Desc->getNumberOfNodes());
9989   int offset2(offset1+m2Desc->getNumberOfNodes());
9990   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9991     {
9992       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9993       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9994       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9995         {
9996           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9997           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9998           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9999           candidates1[0]=i;
10000           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10001           // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
10002           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10003           std::set<INTERP_KERNEL::Node *> nodes;
10004           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10005           std::size_t szz(nodes.size());
10006           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10007           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10008           for(std::size_t iii=0;iii<szz;iii++,itt++)
10009             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10010           // end of protection
10011           // Performs egde cutting:
10012           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10013           delete pol2;
10014           delete pol1;
10015         }
10016       else
10017         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
10018     }
10019 }
10020
10021 /*!
10022  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10023  * It builds the descending connectivity of the two meshes, and then using a binary tree
10024  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10025  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10026  */
10027 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10028                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10029                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10030                                                    std::vector<double>& addCoo,
10031                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10032 {
10033   // Build desc connectivity
10034   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10035   desc2=DataArrayInt::New();
10036   descIndx2=DataArrayInt::New();
10037   revDesc2=DataArrayInt::New();
10038   revDescIndx2=DataArrayInt::New();
10039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10041   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10042   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10043   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10044   std::map<int,int> notUsedMap;
10045   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10046   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10047   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10048 }
10049
10050 /*!
10051  * This method performs the 2nd step of Partition of 2D mesh.
10052  * This method has 4 inputs :
10053  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10054  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10055  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10056  * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
10057  * Nodes end up lying consecutively on a cutted edge.
10058  * \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.
10059  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10060  * \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.
10061  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10062  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10063  */
10064 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10065                                            const std::vector<double>& addCoo,
10066                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10067 {
10068   int offset1=m1->getNumberOfNodes();
10069   int ncell=m2->getNumberOfCells();
10070   const int *c=m2->getNodalConnectivity()->getConstPointer();
10071   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10072   const double *coo=m2->getCoords()->getConstPointer();
10073   const double *cooBis=m1->getCoords()->getConstPointer();
10074   int offset2=offset1+m2->getNumberOfNodes();
10075   intersectEdge.resize(ncell);
10076   for(int i=0;i<ncell;i++,cI++)
10077     {
10078       const std::vector<int>& divs=subDiv[i];
10079       int nnode=cI[1]-cI[0]-1;
10080       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10081       std::map<INTERP_KERNEL::Node *, int> mapp22;
10082       for(int j=0;j<nnode;j++)
10083         {
10084           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10085           int nnid=c[(*cI)+j+1];
10086           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10087           mapp22[nn]=nnid+offset1;
10088         }
10089       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10090       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10091         ((*it).second.first)->decrRef();
10092       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10093       std::map<INTERP_KERNEL::Node *,int> mapp3;
10094       for(std::size_t j=0;j<divs.size();j++)
10095         {
10096           int id=divs[j];
10097           INTERP_KERNEL::Node *tmp=0;
10098           if(id<offset1)
10099             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10100           else if(id<offset2)
10101             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10102           else
10103             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10104           addNodes[j]=tmp;
10105           mapp3[tmp]=id;
10106         }
10107       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10108       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10109         (*it)->decrRef();
10110       e->decrRef();
10111     }
10112 }
10113
10114 /*!
10115  * 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).
10116  * 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
10117  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10118  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10119  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10120  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10121  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10122  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10123  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10124  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10125  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10126  * \param [out] cut3DSuf input/output param.
10127  */
10128 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10129                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10130                                                    const int *desc, const int *descIndx, 
10131                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10132 {
10133   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10134   int nbOf3DSurfCell=(int)cut3DSurf.size();
10135   for(int i=0;i<nbOf3DSurfCell;i++)
10136     {
10137       std::vector<int> res;
10138       int offset=descIndx[i];
10139       int nbOfSeg=descIndx[i+1]-offset;
10140       for(int j=0;j<nbOfSeg;j++)
10141         {
10142           int edgeId=desc[offset+j];
10143           int status=cut3DCurve[edgeId];
10144           if(status!=-2)
10145             {
10146               if(status>-1)
10147                 res.push_back(status);
10148               else
10149                 {
10150                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10151                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10152                 }
10153             }
10154         }
10155       switch(res.size())
10156       {
10157         case 2:
10158           {
10159             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10160             break;
10161           }
10162         case 1:
10163         case 0:
10164           {
10165             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10166             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10167             if(res.size()==2)
10168               {
10169                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10170               }
10171             else
10172               {
10173                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10174               }
10175             break;
10176           }
10177         default:
10178           {// case when plane is on a multi colinear edge of a polyhedron
10179             if((int)res.size()==2*nbOfSeg)
10180               {
10181                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10182               }
10183             else
10184               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10185           }
10186       }
10187     }
10188 }
10189
10190 /*!
10191  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10192  * 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).
10193  * 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
10194  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10195  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10196  * \param desc is the descending connectivity 3D->3DSurf
10197  * \param descIndx is the descending connectivity index 3D->3DSurf
10198  */
10199 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10200                                                   const int *desc, const int *descIndx,
10201                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10202 {
10203   checkFullyDefined();
10204   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10206   const int *nodal3D=_nodal_connec->getConstPointer();
10207   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10208   int nbOfCells=getNumberOfCells();
10209   for(int i=0;i<nbOfCells;i++)
10210     {
10211       std::map<int, std::set<int> > m;
10212       int offset=descIndx[i];
10213       int nbOfFaces=descIndx[i+1]-offset;
10214       int start=-1;
10215       int end=-1;
10216       for(int j=0;j<nbOfFaces;j++)
10217         {
10218           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10219           if(p.first!=-1 && p.second!=-1)
10220             {
10221               if(p.first!=-2)
10222                 {
10223                   start=p.first; end=p.second;
10224                   m[p.first].insert(p.second);
10225                   m[p.second].insert(p.first);
10226                 }
10227               else
10228                 {
10229                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10230                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10231                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10232                   INTERP_KERNEL::NormalizedCellType cmsId;
10233                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10234                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10235                   for(unsigned k=0;k<nbOfNodesSon;k++)
10236                     {
10237                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10238                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10239                     }
10240                 }
10241             }
10242         }
10243       if(m.empty())
10244         continue;
10245       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10246       int prev=end;
10247       while(end!=start)
10248         {
10249           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10250           const std::set<int>& s=(*it).second;
10251           std::set<int> s2; s2.insert(prev);
10252           std::set<int> s3;
10253           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10254           if(s3.size()==1)
10255             {
10256               int val=*s3.begin();
10257               conn.push_back(start);
10258               prev=start;
10259               start=val;
10260             }
10261           else
10262             start=end;
10263         }
10264       conn.push_back(end);
10265       if(conn.size()>3)
10266         {
10267           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10268           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10269           cellIds->pushBackSilent(i);
10270         }
10271     }
10272 }
10273
10274 /*!
10275  * 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
10276  * 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
10277  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10278  * 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
10279  * 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.
10280  * 
10281  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10282  */
10283 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10284 {
10285   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10286   if(sz>=4)
10287     {
10288       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10289       if(cm.getDimension()==2)
10290         {
10291           const int *node=nodalConnBg+1;
10292           int startNode=*node++;
10293           double refX=coords[2*startNode];
10294           for(;node!=nodalConnEnd;node++)
10295             {
10296               if(coords[2*(*node)]<refX)
10297                 {
10298                   startNode=*node;
10299                   refX=coords[2*startNode];
10300                 }
10301             }
10302           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10303           refX=1e300;
10304           double tmp1;
10305           double tmp2[2];
10306           double angle0=-M_PI/2;
10307           //
10308           int nextNode=-1;
10309           int prevNode=-1;
10310           double resRef;
10311           double angleNext=0.;
10312           while(nextNode!=startNode)
10313             {
10314               nextNode=-1;
10315               resRef=1e300;
10316               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10317                 {
10318                   if(*node!=tmpOut.back() && *node!=prevNode)
10319                     {
10320                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10321                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10322                       double res;
10323                       if(angleM<=angle0)
10324                         res=angle0-angleM;
10325                       else
10326                         res=angle0-angleM+2.*M_PI;
10327                       if(res<resRef)
10328                         {
10329                           nextNode=*node;
10330                           resRef=res;
10331                           angleNext=angleM;
10332                         }
10333                     }
10334                 }
10335               if(nextNode!=startNode)
10336                 {
10337                   angle0=angleNext-M_PI;
10338                   if(angle0<-M_PI)
10339                     angle0+=2*M_PI;
10340                   prevNode=tmpOut.back();
10341                   tmpOut.push_back(nextNode);
10342                 }
10343             }
10344           std::vector<int> tmp3(2*(sz-1));
10345           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10346           std::copy(nodalConnBg+1,nodalConnEnd,it);
10347           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10348             {
10349               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10350               return false;
10351             }
10352           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10353             {
10354               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10355               return false;
10356             }
10357           else
10358             {
10359               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10360               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10361               return true;
10362             }
10363         }
10364       else
10365         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10366     }
10367   else
10368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10369 }
10370
10371 /*!
10372  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10373  * 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.
10374  * 
10375  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10376  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10377  * \param [in,out] arr array in which the remove operation will be done.
10378  * \param [in,out] arrIndx array in the remove operation will modify
10379  * \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])
10380  * \return true if \b arr and \b arrIndx have been modified, false if not.
10381  */
10382 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10383 {
10384   if(!arrIndx || !arr)
10385     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10386   if(offsetForRemoval<0)
10387     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10388   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10389   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10390   int *arrIPtr=arrIndx->getPointer();
10391   *arrIPtr++=0;
10392   int previousArrI=0;
10393   const int *arrPtr=arr->getConstPointer();
10394   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10395   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10396     {
10397       if(*arrIPtr-previousArrI>offsetForRemoval)
10398         {
10399           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10400             {
10401               if(s.find(*work)==s.end())
10402                 arrOut.push_back(*work);
10403             }
10404         }
10405       previousArrI=*arrIPtr;
10406       *arrIPtr=(int)arrOut.size();
10407     }
10408   if(arr->getNumberOfTuples()==(int)arrOut.size())
10409     return false;
10410   arr->alloc((int)arrOut.size(),1);
10411   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10412   return true;
10413 }
10414
10415 /*!
10416  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10417  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10418  * The selection of extraction is done standardly in new2old format.
10419  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10420  *
10421  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10422  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10423  * \param [in] arrIn arr origin array from which the extraction will be done.
10424  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10425  * \param [out] arrOut the resulting array
10426  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10427  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10428  */
10429 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10430                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10431 {
10432   if(!arrIn || !arrIndxIn)
10433     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10434   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10435   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10436     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10437   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10438   const int *arrInPtr=arrIn->getConstPointer();
10439   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10440   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10441   if(nbOfGrps<0)
10442     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10443   int maxSizeOfArr=arrIn->getNumberOfTuples();
10444   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10446   arrIo->alloc((int)(sz+1),1);
10447   const int *idsIt=idsOfSelectBg;
10448   int *work=arrIo->getPointer();
10449   *work++=0;
10450   int lgth=0;
10451   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10452     {
10453       if(*idsIt>=0 && *idsIt<nbOfGrps)
10454         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10455       else
10456         {
10457           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10458           throw INTERP_KERNEL::Exception(oss.str().c_str());
10459         }
10460       if(lgth>=work[-1])
10461         *work=lgth;
10462       else
10463         {
10464           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10465           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10466           throw INTERP_KERNEL::Exception(oss.str().c_str());
10467         }
10468     }
10469   arro->alloc(lgth,1);
10470   work=arro->getPointer();
10471   idsIt=idsOfSelectBg;
10472   for(std::size_t i=0;i<sz;i++,idsIt++)
10473     {
10474       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10475         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10476       else
10477         {
10478           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10479           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10480           throw INTERP_KERNEL::Exception(oss.str().c_str());
10481         }
10482     }
10483   arrOut=arro.retn();
10484   arrIndexOut=arrIo.retn();
10485 }
10486
10487 /*!
10488  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10489  * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
10490  * The selection of extraction is done standardly in new2old format.
10491  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10492  *
10493  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10494  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10495  * \param [in] arrIn arr origin array from which the extraction will be done.
10496  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10497  * \param [out] arrOut the resulting array
10498  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10499  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10500  */
10501 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10502                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10503 {
10504   if(!arrIn || !arrIndxIn)
10505     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10506   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10507   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10508     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10509   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10510   const int *arrInPtr=arrIn->getConstPointer();
10511   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10512   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10513   if(nbOfGrps<0)
10514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10515   int maxSizeOfArr=arrIn->getNumberOfTuples();
10516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10518   arrIo->alloc((int)(sz+1),1);
10519   int idsIt=idsOfSelectStart;
10520   int *work=arrIo->getPointer();
10521   *work++=0;
10522   int lgth=0;
10523   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10524     {
10525       if(idsIt>=0 && idsIt<nbOfGrps)
10526         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10527       else
10528         {
10529           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10530           throw INTERP_KERNEL::Exception(oss.str().c_str());
10531         }
10532       if(lgth>=work[-1])
10533         *work=lgth;
10534       else
10535         {
10536           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10537           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10538           throw INTERP_KERNEL::Exception(oss.str().c_str());
10539         }
10540     }
10541   arro->alloc(lgth,1);
10542   work=arro->getPointer();
10543   idsIt=idsOfSelectStart;
10544   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10545     {
10546       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10547         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10548       else
10549         {
10550           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10551           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10552           throw INTERP_KERNEL::Exception(oss.str().c_str());
10553         }
10554     }
10555   arrOut=arro.retn();
10556   arrIndexOut=arrIo.retn();
10557 }
10558
10559 /*!
10560  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10561  * 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
10562  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10563  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10564  *
10565  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10566  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10567  * \param [in] arrIn arr origin array from which the extraction will be done.
10568  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10569  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10570  * \param [in] srcArrIndex index array of \b srcArr
10571  * \param [out] arrOut the resulting array
10572  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10573  * 
10574  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10575  */
10576 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10577                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10578                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10579 {
10580   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10583   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10584   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10585   std::vector<bool> v(nbOfTuples,true);
10586   int offset=0;
10587   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10588   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10589   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10590     {
10591       if(*it>=0 && *it<nbOfTuples)
10592         {
10593           v[*it]=false;
10594           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10595         }
10596       else
10597         {
10598           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10599           throw INTERP_KERNEL::Exception(oss.str().c_str());
10600         }
10601     }
10602   srcArrIndexPtr=srcArrIndex->getConstPointer();
10603   arrIo->alloc(nbOfTuples+1,1);
10604   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10605   const int *arrInPtr=arrIn->getConstPointer();
10606   const int *srcArrPtr=srcArr->getConstPointer();
10607   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10608   int *arroPtr=arro->getPointer();
10609   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10610     {
10611       if(v[ii])
10612         {
10613           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10614           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10615         }
10616       else
10617         {
10618           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10619           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10620           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10621         }
10622     }
10623   arrOut=arro.retn();
10624   arrIndexOut=arrIo.retn();
10625 }
10626
10627 /*!
10628  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10629  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10630  *
10631  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10632  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10633  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10634  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10635  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10636  * \param [in] srcArrIndex index array of \b srcArr
10637  * 
10638  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10639  */
10640 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10641                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10642 {
10643   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10644     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10645   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10646   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10647   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10648   int *arrInOutPtr=arrInOut->getPointer();
10649   const int *srcArrPtr=srcArr->getConstPointer();
10650   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10651     {
10652       if(*it>=0 && *it<nbOfTuples)
10653         {
10654           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10655             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10656           else
10657             {
10658               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] !";
10659               throw INTERP_KERNEL::Exception(oss.str().c_str());
10660             }
10661         }
10662       else
10663         {
10664           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10665           throw INTERP_KERNEL::Exception(oss.str().c_str());
10666         }
10667     }
10668 }
10669
10670 /*!
10671  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10672  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10673  * 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]].
10674  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10675  * A negative value in \b arrIn means that it is ignored.
10676  * 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.
10677  * 
10678  * \param [in] arrIn arr origin array from which the extraction will be done.
10679  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10680  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10681  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10682  */
10683 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10684 {
10685   int seed=0,nbOfDepthPeelingPerformed=0;
10686   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10687 }
10688
10689 /*!
10690  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10691  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10692  * 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]].
10693  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10694  * A negative value in \b arrIn means that it is ignored.
10695  * 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.
10696  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10697  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10698  * \param [in] arrIn arr origin array from which the extraction will be done.
10699  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10700  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10701  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10702  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10703  * \sa MEDCouplingUMesh::partitionBySpreadZone
10704  */
10705 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10706 {
10707   nbOfDepthPeelingPerformed=0;
10708   if(!arrIndxIn)
10709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10710   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10711   if(nbOfTuples<=0)
10712     {
10713       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10714       return ret;
10715     }
10716   //
10717   std::vector<bool> fetched(nbOfTuples,false);
10718   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10719 }
10720
10721 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10722 {
10723   nbOfDepthPeelingPerformed=0;
10724   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10726   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10727   std::vector<bool> fetched2(nbOfTuples,false);
10728   int i=0;
10729   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
10730     {
10731       if(*seedElt>=0 && *seedElt<nbOfTuples)
10732         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
10733       else
10734         { 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()); }
10735     }
10736   const int *arrInPtr=arrIn->getConstPointer();
10737   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10738   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
10739   std::vector<int> idsToFetch1(seedBg,seedEnd);
10740   std::vector<int> idsToFetch2;
10741   std::vector<int> *idsToFetch=&idsToFetch1;
10742   std::vector<int> *idsToFetchOther=&idsToFetch2;
10743   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
10744     {
10745       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
10746         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
10747           if(!fetched[*it2])
10748             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10749       std::swap(idsToFetch,idsToFetchOther);
10750       idsToFetchOther->clear();
10751       nbOfDepthPeelingPerformed++;
10752     }
10753   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10754   i=0;
10755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10756   int *retPtr=ret->getPointer();
10757   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10758     if(*it)
10759       *retPtr++=i;
10760   return ret.retn();
10761 }
10762
10763 /*!
10764  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10765  * 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
10766  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10767  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10768  *
10769  * \param [in] start begin of set of ids of the input extraction (included)
10770  * \param [in] end end of set of ids of the input extraction (excluded)
10771  * \param [in] step step of the set of ids in range mode.
10772  * \param [in] arrIn arr origin array from which the extraction will be done.
10773  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10774  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10775  * \param [in] srcArrIndex index array of \b srcArr
10776  * \param [out] arrOut the resulting array
10777  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10778  * 
10779  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10780  */
10781 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10782                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10783                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10784 {
10785   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10789   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10790   int offset=0;
10791   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10792   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10793   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10794   int it=start;
10795   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10796     {
10797       if(it>=0 && it<nbOfTuples)
10798         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10799       else
10800         {
10801           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10802           throw INTERP_KERNEL::Exception(oss.str().c_str());
10803         }
10804     }
10805   srcArrIndexPtr=srcArrIndex->getConstPointer();
10806   arrIo->alloc(nbOfTuples+1,1);
10807   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10808   const int *arrInPtr=arrIn->getConstPointer();
10809   const int *srcArrPtr=srcArr->getConstPointer();
10810   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10811   int *arroPtr=arro->getPointer();
10812   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10813     {
10814       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10815       if(pos<0)
10816         {
10817           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10818           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10819         }
10820       else
10821         {
10822           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10823           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10824         }
10825     }
10826   arrOut=arro.retn();
10827   arrIndexOut=arrIo.retn();
10828 }
10829
10830 /*!
10831  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10832  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10833  *
10834  * \param [in] start begin of set of ids of the input extraction (included)
10835  * \param [in] end end of set of ids of the input extraction (excluded)
10836  * \param [in] step step of the set of ids in range mode.
10837  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10838  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10839  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10840  * \param [in] srcArrIndex index array of \b srcArr
10841  * 
10842  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10843  */
10844 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10845                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10846 {
10847   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10849   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10850   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10851   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10852   int *arrInOutPtr=arrInOut->getPointer();
10853   const int *srcArrPtr=srcArr->getConstPointer();
10854   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10855   int it=start;
10856   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10857     {
10858       if(it>=0 && it<nbOfTuples)
10859         {
10860           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10861             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10862           else
10863             {
10864               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10865               throw INTERP_KERNEL::Exception(oss.str().c_str());
10866             }
10867         }
10868       else
10869         {
10870           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10871           throw INTERP_KERNEL::Exception(oss.str().c_str());
10872         }
10873     }
10874 }
10875
10876 /*!
10877  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10878  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10879  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10880  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10881  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10882  * 
10883  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10884  */
10885 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10886 {
10887   checkFullyDefined();
10888   int mdim=getMeshDimension();
10889   int spaceDim=getSpaceDimension();
10890   if(mdim!=spaceDim)
10891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10892   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10893   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10894   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10895   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10896   ret->setCoords(getCoords());
10897   ret->allocateCells((int)partition.size());
10898   //
10899   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10900     {
10901       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10902       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10903       switch(mdim)
10904       {
10905         case 2:
10906           cell=tmp->buildUnionOf2DMesh();
10907           break;
10908         case 3:
10909           cell=tmp->buildUnionOf3DMesh();
10910           break;
10911         default:
10912           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10913       }
10914
10915       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10916     }
10917   //
10918   ret->finishInsertingCells();
10919   return ret.retn();
10920 }
10921
10922 /*!
10923  * This method partitions \b this into contiguous zone.
10924  * This method only needs a well defined connectivity. Coordinates are not considered here.
10925  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10926  */
10927 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10928 {
10929   int nbOfCellsCur=getNumberOfCells();
10930   std::vector<DataArrayInt *> ret;
10931   if(nbOfCellsCur<=0)
10932     return ret;
10933   DataArrayInt *neigh=0,*neighI=0;
10934   computeNeighborsOfCells(neigh,neighI);
10935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10936   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10937   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10938   int seed=0;
10939   while(seed<nbOfCellsCur)
10940     {
10941       int nbOfPeelPerformed=0;
10942       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10943       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10944     }
10945   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10946     ret.push_back((*it).retn());
10947   return ret;
10948 }
10949
10950 /*!
10951  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10952  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10953  *
10954  * \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.
10955  * \return a newly allocated DataArrayInt to be managed by the caller.
10956  * \throw In case of \a code has not the right format (typically of size 3*n)
10957  */
10958 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10959 {
10960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10961   std::size_t nb=code.size()/3;
10962   if(code.size()%3!=0)
10963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10964   ret->alloc((int)nb,2);
10965   int *retPtr=ret->getPointer();
10966   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10967     {
10968       retPtr[0]=code[3*i+2];
10969       retPtr[1]=code[3*i+2]+code[3*i+1];
10970     }
10971   return ret.retn();
10972 }
10973
10974 /*!
10975  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10976  * All cells in \a this are expected to be linear 3D cells.
10977  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10978  * It leads to an increase to number of cells.
10979  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10980  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
10981  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10982  *
10983  * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
10984  *                      For all other cells, the splitting policy will be ignored.
10985  * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. 
10986  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10987  *          an id of old cell producing it. The caller is to delete this array using
10988  *         decrRef() as it is no more needed.
10989  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10990  *
10991  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
10992  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10993  * 
10994  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10995  * \throw If \a this is not fully constituted with linear 3D cells.
10996  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10997  */
10998 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10999 {
11000   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11001   checkConnectivityFullyDefined();
11002   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11003     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11004   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11005   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11006   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11007   int *retPt(ret->getPointer());
11008   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11009   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11010   const int *oldc(_nodal_connec->begin());
11011   const int *oldci(_nodal_connec_index->begin());
11012   const double *coords(_coords->begin());
11013   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11014     {
11015       std::vector<int> a; std::vector<double> b;
11016       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11017       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11018       const int *aa(&a[0]);
11019       if(!b.empty())
11020         {
11021           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11022             if(*it<0)
11023               *it=(-(*(it))-1+nbNodes);
11024           addPts->insertAtTheEnd(b.begin(),b.end());
11025           nbNodes+=(int)b.size()/3;
11026         }
11027       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11028         newConn->insertAtTheEnd(aa,aa+4);
11029     }
11030   if(!addPts->empty())
11031     {
11032       addPts->rearrange(3);
11033       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11034       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11035       ret0->setCoords(addPts);
11036     }
11037   else
11038     {
11039       nbOfAdditionalPoints=0;
11040       ret0->setCoords(getCoords());
11041     }
11042   ret0->setNodalConnectivity(newConn);
11043   //
11044   ret->computeOffsets2();
11045   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11046   return ret0.retn();
11047 }
11048
11049 /*!
11050  * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch). 
11051  *
11052  * \sa MEDCouplingUMesh::split2DCells
11053  */
11054 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11055 {
11056   checkConnectivityFullyDefined();
11057   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11059   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11060   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11061   int prevPosOfCi(ciPtr[0]);
11062   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11063     {
11064       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11065       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11066       for(int j=0;j<sz;j++)
11067         {
11068           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11069           for(int k=0;k<sz2;k++)
11070             *cPtr++=subPtr[offset2+k];
11071           if(j!=sz-1)
11072             *cPtr++=oldConn[prevPosOfCi+j+2];
11073           deltaSz+=sz2;
11074         }
11075       prevPosOfCi=ciPtr[1];
11076       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11077     }
11078   if(c->end()!=cPtr)
11079     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11080   _nodal_connec->decrRef();
11081   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11082 }
11083
11084 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11085 {
11086   if(id!=-1)
11087     return id;
11088   else
11089     {
11090       int ret(nodesCnter++);
11091       double newPt[2];
11092       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11093       addCoo.insertAtTheEnd(newPt,newPt+2);
11094       return ret;
11095     }
11096 }
11097
11098 /// @cond INTERNAL
11099
11100 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11101 {
11102   int tmp[3];
11103   int trueStart(start>=0?start:nbOfEdges+start);
11104   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11105   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11106   if(linOrArc)
11107     {
11108       if(stp-start>1)
11109         {
11110           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11111           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11112           middles.push_back(tmp3+offset);
11113         }
11114       else
11115         middles.push_back(connBg[trueStart+nbOfEdges]);
11116     }
11117 }
11118
11119 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11120 {
11121   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11122   newConnOfCell->pushBackSilent(tmpEnd);
11123   if(linOrArc)
11124     {
11125       if(stp-start>1)
11126         {
11127           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11128           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11129           middles.push_back(tmp3+offset);
11130         }
11131       else
11132         middles.push_back(connBg[start+nbOfEdges]);
11133     }
11134 }
11135
11136 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11137 {
11138   if(linOrArc)
11139     {
11140       if(stp-start>1)
11141         {
11142           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11143           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11144           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11145           middles.push_back(tmp3+offset);
11146         }
11147       else
11148         middles.push_back(connBg[start+nbOfEdges]);
11149     }
11150 }
11151
11152 /// @cond INTERNAL
11153
11154 /*!
11155  * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
11156  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11157  */
11158 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11159 {
11160   std::size_t sz(std::distance(connBg,connEnd));
11161   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11162     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11163   sz--;
11164   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11165   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11166   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
11167   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11168   INTERP_KERNEL::NormalizedCellType typeOfSon;
11169   std::vector<int> middles;
11170   bool ret(false);
11171   for(;nbOfHit<nbs;nbOfTurn++)
11172     {
11173       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11174       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11175       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11176       posEndElt++;
11177       nbOfHit++;
11178       unsigned endI(nbs-nbOfHit);
11179       for(unsigned i=0;i<endI;i++)
11180         {
11181           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
11182           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11183           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11184           bool isColinear(eint->areColinears());
11185           if(isColinear)
11186             {
11187               nbOfHit++;
11188               posEndElt++;
11189               ret=true;
11190             }
11191           delete eint;
11192           eCand->decrRef();
11193           if(!isColinear)
11194             {
11195               if(nbOfTurn==0)
11196                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
11197                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
11198                   for(unsigned ii=0;ii<endII;ii++)
11199                     {
11200                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
11201                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
11202                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
11203                       isColinear=eint->areColinears();
11204                       if(isColinear)
11205                         {
11206                           nbOfHit++;
11207                           posBaseElt--;
11208                           ret=true;
11209                         }
11210                       delete eint;
11211                       eCand->decrRef();
11212                       if(!isColinear)
11213                         break;
11214                     }
11215                 }
11216               break;
11217             }
11218         }
11219       //push [posBaseElt,posEndElt) in newConnOfCell using e
11220       if(nbOfTurn==0)
11221         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11222       else if(nbOfHit!=nbs)
11223         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11224       else
11225         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11226       posBaseElt=posEndElt;
11227       e->decrRef();
11228     }
11229   if(!middles.empty())
11230     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11231   return ret;
11232 }
11233
11234 /*!
11235  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11236  *
11237  * \return  int - the number of new nodes created.
11238  * \sa MEDCouplingUMesh::split2DCells
11239  */
11240 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11241 {
11242   checkCoherency();
11243   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11245   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11246   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11247   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11248   const double *oldCoordsPtr(getCoords()->begin());
11249   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11250   int prevPosOfCi(ciPtr[0]);
11251   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11252     {
11253       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11254       for(int j=0;j<sz;j++)
11255         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11256       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11257       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11258         {
11259           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11260           if(sz2==0)
11261             {
11262               if(j<sz-1)
11263                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11264               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11265               continue;
11266             }
11267           std::vector<INTERP_KERNEL::Node *> ns(3);
11268           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11269           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11270           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11271           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11272           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11273             {
11274               cPtr[1]=subPtr[offset2+k];
11275               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11276             }
11277           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11278           if(j!=sz-1)
11279             { cPtr[1]=tmpEnd; }
11280           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11281         }
11282       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11283       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11284     }
11285   if(c->end()!=cPtr)
11286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11287   _nodal_connec->decrRef();
11288   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11289   addCoo->rearrange(2);
11290   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11291   setCoords(coo);
11292   return addCoo->getNumberOfTuples();
11293 }
11294
11295 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11296     _own_cell(true),_cell_id(-1),_nb_cell(0)
11297 {
11298   if(mesh)
11299     {
11300       mesh->incrRef();
11301       _nb_cell=mesh->getNumberOfCells();
11302     }
11303 }
11304
11305 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11306 {
11307   if(_mesh)
11308     _mesh->decrRef();
11309   if(_own_cell)
11310     delete _cell;
11311 }
11312
11313 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11314     _own_cell(false),_cell_id(bg-1),
11315     _nb_cell(end)
11316 {
11317   if(mesh)
11318     mesh->incrRef();
11319 }
11320
11321 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11322 {
11323   _cell_id++;
11324   if(_cell_id<_nb_cell)
11325     {
11326       _cell->next();
11327       return _cell;
11328     }
11329   else
11330     return 0;
11331 }
11332
11333 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11334 {
11335   if(_mesh)
11336     _mesh->incrRef();
11337 }
11338
11339 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11340 {
11341   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11342 }
11343
11344 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11345 {
11346   if(_mesh)
11347     _mesh->decrRef();
11348 }
11349
11350 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11351     _itc(itc),
11352     _bg(bg),_end(end)
11353 {
11354   if(_mesh)
11355     _mesh->incrRef();
11356 }
11357
11358 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11359 {
11360   if(_mesh)
11361     _mesh->decrRef();
11362 }
11363
11364 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11365 {
11366   return _type;
11367 }
11368
11369 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11370 {
11371   return _end-_bg;
11372 }
11373
11374 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11375 {
11376   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11377 }
11378
11379 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11380 {
11381   if(mesh)
11382     {
11383       mesh->incrRef();
11384       _nb_cell=mesh->getNumberOfCells();
11385     }
11386 }
11387
11388 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11389 {
11390   if(_mesh)
11391     _mesh->decrRef();
11392   delete _cell;
11393 }
11394
11395 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11396 {
11397   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11398   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11399   if(_cell_id<_nb_cell)
11400     {
11401       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11402       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11403       int startId=_cell_id;
11404       _cell_id+=nbOfElems;
11405       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11406     }
11407   else
11408     return 0;
11409 }
11410
11411 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11412 {
11413   if(mesh)
11414     {
11415       _conn=mesh->getNodalConnectivity()->getPointer();
11416       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11417     }
11418 }
11419
11420 void MEDCouplingUMeshCell::next()
11421 {
11422   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11423     {
11424       _conn+=_conn_lgth;
11425       _conn_indx++;
11426     }
11427   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11428 }
11429
11430 std::string MEDCouplingUMeshCell::repr() const
11431 {
11432   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11433     {
11434       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11435       oss << " : ";
11436       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11437       return oss.str();
11438     }
11439   else
11440     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11441 }
11442
11443 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11444 {
11445   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11446     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11447   else
11448     return INTERP_KERNEL::NORM_ERROR;
11449 }
11450
11451 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11452 {
11453   lgth=_conn_lgth;
11454   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11455     return _conn;
11456   else
11457     return 0;
11458 }