Salome HOME
getSkewField(): documentation.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  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 "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace MEDCoupling;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 /// @cond INTERNAL
57 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 };
58 /// @endcond
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
61 {
62   return new MEDCouplingUMesh;
63 }
64
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
66 {
67   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68   ret->setName(meshName);
69   ret->setMeshDimension(meshDim);
70   return ret;
71 }
72
73 /*!
74  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
80 {
81   return clone(true);
82 }
83
84
85 /*!
86  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88  * this mesh are shared by the new mesh.
89  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90  *          delete this mesh using decrRef() as it is no more needed. 
91  */
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
93 {
94   return new MEDCouplingUMesh(*this,recDeepCpy);
95 }
96
97 /*!
98  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
99  * The coordinates are shared between \a this and the returned instance.
100  * 
101  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102  * \sa MEDCouplingUMesh::deepCopy
103  */
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
105 {
106   checkConnectivityFullyDefined();
107   MCAuto<MEDCouplingUMesh> ret=clone(false);
108   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
109   ret->setConnectivity(c,ci);
110   return ret.retn();
111 }
112
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
114 {
115   if(!other)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
118   if(!otherC)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
122 }
123
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
125 {
126   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127   return ret;
128 }
129
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
131 {
132   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133   ret.push_back(_nodal_connec);
134   ret.push_back(_nodal_connec_index);
135   return ret;
136 }
137
138 void MEDCouplingUMesh::updateTime() const
139 {
140   MEDCouplingPointSet::updateTime();
141   if(_nodal_connec)
142     {
143       updateTimeWith(*_nodal_connec);
144     }
145   if(_nodal_connec_index)
146     {
147       updateTimeWith(*_nodal_connec_index);
148     }
149 }
150
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 {
153 }
154
155 /*!
156  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157  * then \a this mesh is most probably is writable, exchangeable and available for most
158  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159  * this method to check that all is in order with \a this mesh.
160  *  \throw If the mesh dimension is not set.
161  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
162  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163  *  \throw If the connectivity data array has more than one component.
164  *  \throw If the connectivity data array has a named component.
165  *  \throw If the connectivity index data array has more than one component.
166  *  \throw If the connectivity index data array has a named component.
167  */
168 void MEDCouplingUMesh::checkConsistencyLight() const
169 {
170   if(_mesh_dim<-1)
171     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172   if(_mesh_dim!=-1)
173     MEDCouplingPointSet::checkConsistencyLight();
174   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
175     {
176       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
177         {
178           std::ostringstream message;
179           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180           throw INTERP_KERNEL::Exception(message.str().c_str());
181         }
182     }
183   if(_nodal_connec)
184     {
185       if(_nodal_connec->getNumberOfComponents()!=1)
186         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187       if(_nodal_connec->getInfoOnComponent(0)!="")
188         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189     }
190   else
191     if(_mesh_dim!=-1)
192       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193   if(_nodal_connec_index)
194     {
195       if(_nodal_connec_index->getNumberOfComponents()!=1)
196         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197       if(_nodal_connec_index->getInfoOnComponent(0)!="")
198         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199     }
200   else
201     if(_mesh_dim!=-1)
202       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 }
204
205 /*!
206  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207  * then \a this mesh is most probably is writable, exchangeable and available for all
208  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
209  * method thoroughly checks the nodal connectivity.
210  *  \param [in] eps - a not used parameter.
211  *  \throw If the mesh dimension is not set.
212  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
213  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214  *  \throw If the connectivity data array has more than one component.
215  *  \throw If the connectivity data array has a named component.
216  *  \throw If the connectivity index data array has more than one component.
217  *  \throw If the connectivity index data array has a named component.
218  *  \throw If number of nodes defining an element does not correspond to the type of element.
219  *  \throw If the nodal connectivity includes an invalid node id.
220  */
221 void MEDCouplingUMesh::checkConsistency(double eps) const
222 {
223   checkConsistencyLight();
224   if(_mesh_dim==-1)
225     return ;
226   int meshDim=getMeshDimension();
227   int nbOfNodes=getNumberOfNodes();
228   int nbOfCells=getNumberOfCells();
229   const int *ptr=_nodal_connec->getConstPointer();
230   const int *ptrI=_nodal_connec_index->getConstPointer();
231   for(int i=0;i<nbOfCells;i++)
232     {
233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234       if((int)cm.getDimension()!=meshDim)
235         {
236           std::ostringstream oss;
237           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238           throw INTERP_KERNEL::Exception(oss.str().c_str());
239         }
240       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
241       if(!cm.isDynamic())
242         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
243           {
244             std::ostringstream oss;
245             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
246             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247             throw INTERP_KERNEL::Exception(oss.str().c_str());
248           }
249       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
251           {
252             std::ostringstream oss;
253             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
254             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255             throw INTERP_KERNEL::Exception(oss.str().c_str());
256           }
257       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
258         {
259           int nodeId=*w;
260           if(nodeId>=0)
261             {
262               if(nodeId>=nbOfNodes)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268           else if(nodeId<-1)
269             {
270               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271               throw INTERP_KERNEL::Exception(oss.str().c_str());
272             }
273           else
274             {
275               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
276                 {
277                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278                   throw INTERP_KERNEL::Exception(oss.str().c_str());
279                 }
280             }
281         }
282     }
283 }
284
285 /*!
286  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
287  * elements contained in the mesh. For more info on the mesh dimension see
288  * \ref MEDCouplingUMeshPage.
289  *  \param [in] meshDim - a new mesh dimension.
290  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
291  */
292 void MEDCouplingUMesh::setMeshDimension(int meshDim)
293 {
294   if(meshDim<-1 || meshDim>3)
295     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
296   _mesh_dim=meshDim;
297   declareAsNew();
298 }
299
300 /*!
301  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
302  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
303  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
304  *
305  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
306  *
307  *  \if ENABLE_EXAMPLES
308  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
309  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
310  *  \endif
311  */
312 void MEDCouplingUMesh::allocateCells(int nbOfCells)
313 {
314   if(nbOfCells<0)
315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
316   if(_nodal_connec_index)
317     {
318       _nodal_connec_index->decrRef();
319     }
320   if(_nodal_connec)
321     {
322       _nodal_connec->decrRef();
323     }
324   _nodal_connec_index=DataArrayInt::New();
325   _nodal_connec_index->reserve(nbOfCells+1);
326   _nodal_connec_index->pushBackSilent(0);
327   _nodal_connec=DataArrayInt::New();
328   _nodal_connec->reserve(2*nbOfCells);
329   _types.clear();
330   declareAsNew();
331 }
332
333 /*!
334  * Appends a cell to the connectivity array. For deeper understanding what is
335  * happening see \ref MEDCouplingUMeshNodalConnectivity.
336  *  \param [in] type - type of cell to add.
337  *  \param [in] size - number of nodes constituting this cell.
338  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
339  * 
340  *  \if ENABLE_EXAMPLES
341  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
343  *  \endif
344  */
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
346 {
347   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348   if(_nodal_connec_index==0)
349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350   if((int)cm.getDimension()==_mesh_dim)
351     {
352       if(!cm.isDynamic())
353         if(size!=(int)cm.getNumberOfNodes())
354           {
355             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357             throw INTERP_KERNEL::Exception(oss.str().c_str());
358           }
359       int idx=_nodal_connec_index->back();
360       int val=idx+size+1;
361       _nodal_connec_index->pushBackSilent(val);
362       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
363       _types.insert(type);
364     }
365   else
366     {
367       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370       throw INTERP_KERNEL::Exception(oss.str().c_str());
371     }
372 }
373
374 /*!
375  * Compacts data arrays to release unused memory. This method is to be called after
376  * finishing cell insertion using \a this->insertNextCell().
377  * 
378  *  \if ENABLE_EXAMPLES
379  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
380  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
381  *  \endif
382  */
383 void MEDCouplingUMesh::finishInsertingCells()
384 {
385   _nodal_connec->pack();
386   _nodal_connec_index->pack();
387   _nodal_connec->declareAsNew();
388   _nodal_connec_index->declareAsNew();
389   updateTime();
390 }
391
392 /*!
393  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
394  * Useful for python users.
395  */
396 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
397 {
398   return new MEDCouplingUMeshCellIterator(this);
399 }
400
401 /*!
402  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
403  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
404  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
405  * Useful for python users.
406  */
407 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
408 {
409   if(!checkConsecutiveCellTypes())
410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
411   return new MEDCouplingUMeshCellByTypeEntry(this);
412 }
413
414 /*!
415  * Returns a set of all cell types available in \a this mesh.
416  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
417  * \warning this method does not throw any exception even if \a this is not defined.
418  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
419  */
420 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
421 {
422   return _types;
423 }
424
425 /*!
426  * This method returns the sorted list of geometric types in \a this.
427  * 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
428  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
429  *
430  * \throw if connectivity in \a this is not correctly defined.
431  *  
432  * \sa MEDCouplingMesh::getAllGeoTypes
433  */
434 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
435 {
436   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
437   checkConnectivityFullyDefined();
438   int nbOfCells(getNumberOfCells());
439   if(nbOfCells==0)
440     return ret;
441   if(getNodalConnectivityArrayLen()<1)
442     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
443   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
444   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
445   for(int i=1;i<nbOfCells;i++,ci++)
446     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
447       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
448   return ret;
449 }
450
451 /*!
452  * This method is a method that compares \a this and \a other.
453  * This method compares \b all attributes, even names and component names.
454  */
455 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
456 {
457   if(!other)
458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
459   std::ostringstream oss; oss.precision(15);
460   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
461   if(!otherC)
462     {
463       reason="mesh given in input is not castable in MEDCouplingUMesh !";
464       return false;
465     }
466   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
467     return false;
468   if(_mesh_dim!=otherC->_mesh_dim)
469     {
470       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
471       reason=oss.str();
472       return false;
473     }
474   if(_types!=otherC->_types)
475     {
476       oss << "umesh geometric type mismatch :\nThis geometric types are :";
477       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
478         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
479       oss << "\nOther geometric types are :";
480       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
481         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
482       reason=oss.str();
483       return false;
484     }
485   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
486     if(_nodal_connec==0 || otherC->_nodal_connec==0)
487       {
488         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
489         return false;
490       }
491   if(_nodal_connec!=otherC->_nodal_connec)
492     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
493       {
494         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
495         return false;
496       }
497   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
498     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
499       {
500         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
501         return false;
502       }
503   if(_nodal_connec_index!=otherC->_nodal_connec_index)
504     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
505       {
506         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
507         return false;
508       }
509   return true;
510 }
511
512 /*!
513  * Checks if data arrays of this mesh (node coordinates, nodal
514  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
515  * not considered.
516  *  \param [in] other - the mesh to compare with.
517  *  \param [in] prec - precision value used to compare node coordinates.
518  *  \return bool - \a true if the two meshes are same.
519  */
520 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
521 {
522   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
523   if(!otherC)
524     return false;
525   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
526     return false;
527   if(_mesh_dim!=otherC->_mesh_dim)
528     return false;
529   if(_types!=otherC->_types)
530     return false;
531   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
532     if(_nodal_connec==0 || otherC->_nodal_connec==0)
533       return false;
534   if(_nodal_connec!=otherC->_nodal_connec)
535     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
536       return false;
537   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
538     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
539       return false;
540   if(_nodal_connec_index!=otherC->_nodal_connec_index)
541     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
542       return false;
543   return true;
544 }
545
546 /*!
547  * Checks if \a this and \a other meshes are geometrically equivalent with high
548  * probability, else an exception is thrown. The meshes are considered equivalent if
549  * (1) meshes contain the same number of nodes and the same number of elements of the
550  * same types (2) three cells of the two meshes (first, last and middle) are based
551  * on coincident nodes (with a specified precision).
552  *  \param [in] other - the mesh to compare with.
553  *  \param [in] prec - the precision used to compare nodes of the two meshes.
554  *  \throw If the two meshes do not match.
555  */
556 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
557 {
558   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
559   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
560   if(!otherC)
561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
562 }
563
564 /*!
565  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
566  * cells each node belongs to.
567  * \warning For speed reasons, this method does not check if node ids in the nodal
568  *          connectivity correspond to the size of node coordinates array.
569  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
570  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
571  *        dividing cell ids in \a revNodal into groups each referring to one
572  *        node. Its every element (except the last one) is an index pointing to the
573  *         first id of a group of cells. For example cells sharing the node #1 are 
574  *        described by following range of indices: 
575  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
576  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
577  *        Number of cells sharing the *i*-th node is
578  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
579  * \throw If the coordinates array is not set.
580  * \throw If the nodal connectivity of cells is not defined.
581  * 
582  * \if ENABLE_EXAMPLES
583  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
584  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
585  * \endif
586  */
587 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
588 {
589   checkFullyDefined();
590   int nbOfNodes=getNumberOfNodes();
591   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
592   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
593   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
594   const int *conn=_nodal_connec->getConstPointer();
595   const int *connIndex=_nodal_connec_index->getConstPointer();
596   int nbOfCells=getNumberOfCells();
597   int nbOfEltsInRevNodal=0;
598   for(int eltId=0;eltId<nbOfCells;eltId++)
599     {
600       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
601       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
602       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603         if(*iter>=0)//for polyhedrons
604           {
605             nbOfEltsInRevNodal++;
606             revNodalIndxPtr[(*iter)+1]++;
607           }
608     }
609   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613   for(int eltId=0;eltId<nbOfCells;eltId++)
614     {
615       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618         if(*iter>=0)//for polyhedrons
619           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
620     }
621 }
622
623 /// @cond INTERNAL
624
625 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
626 {
627   return id;
628 }
629
630 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
631 {
632   if(!compute)
633     return id+1;
634   else
635     {
636       if(cm.getOrientationStatus(nb,conn1,conn2))
637         return id+1;
638       else
639         return -(id+1);
640     }
641 }
642
643 class MinusOneSonsGenerator
644 {
645 public:
646   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
647   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
648   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
649   static const int DELTA=1;
650 private:
651   const INTERP_KERNEL::CellModel& _cm;
652 };
653
654 class MinusOneSonsGeneratorBiQuadratic
655 {
656 public:
657   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
658   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
659   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
660   static const int DELTA=1;
661 private:
662   const INTERP_KERNEL::CellModel& _cm;
663 };
664
665 class MinusTwoSonsGenerator
666 {
667 public:
668   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
669   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
670   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
671   static const int DELTA=2;
672 private:
673   const INTERP_KERNEL::CellModel& _cm;
674 };
675
676 /// @endcond
677
678 /*!
679  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
680  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
681  * describing correspondence between cells of \a this and the result meshes are
682  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
683  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
684  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
685  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
686  * \warning For speed reasons, this method does not check if node ids in the nodal
687  *          connectivity correspond to the size of node coordinates array.
688  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
689  *          to write this mesh to the MED file, its cells must be sorted using
690  *          sortCellsInMEDFileFrmt().
691  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
692  *         each cell of \a this mesh.
693  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
694  *        dividing cell ids in \a desc into groups each referring to one
695  *        cell of \a this mesh. Its every element (except the last one) is an index
696  *        pointing to the first id of a group of cells. For example cells of the
697  *        result mesh bounding the cell #1 of \a this mesh are described by following
698  *        range of indices:
699  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
700  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
701  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
702  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
703  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
704  *         by each cell of the result mesh.
705  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
706  *        in the result mesh,
707  *        dividing cell ids in \a revDesc into groups each referring to one
708  *        cell of the result mesh the same way as \a descIndx divides \a desc.
709  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
710  *        delete this mesh using decrRef() as it is no more needed.
711  *  \throw If the coordinates array is not set.
712  *  \throw If the nodal connectivity of cells is node defined.
713  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
714  *         revDescIndx == NULL.
715  * 
716  *  \if ENABLE_EXAMPLES
717  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
718  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
719  *  \endif
720  * \sa buildDescendingConnectivity2()
721  */
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
723 {
724   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
725 }
726
727 /*!
728  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732  * \sa MEDCouplingUMesh::buildDescendingConnectivity
733  */
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
735 {
736   checkFullyDefined();
737   if(getMeshDimension()!=3)
738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
740 }
741
742 /*!
743  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744  * this->getMeshDimension(), that bound cells of \a this mesh. In
745  * addition arrays describing correspondence between cells of \a this and the result
746  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
747  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748  *  mesh. This method differs from buildDescendingConnectivity() in that apart
749  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750  * result meshes. So a positive id means that order of nodes in corresponding cells
751  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753  * i.e. cell ids are one-based.
754  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
755  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
756  * \warning For speed reasons, this method does not check if node ids in the nodal
757  *          connectivity correspond to the size of node coordinates array.
758  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759  *          to write this mesh to the MED file, its cells must be sorted using
760  *          sortCellsInMEDFileFrmt().
761  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
762  *         each cell of \a this mesh.
763  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764  *        dividing cell ids in \a desc into groups each referring to one
765  *        cell of \a this mesh. Its every element (except the last one) is an index
766  *        pointing to the first id of a group of cells. For example cells of the
767  *        result mesh bounding the cell #1 of \a this mesh are described by following
768  *        range of indices:
769  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774  *         by each cell of the result mesh.
775  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
776  *        in the result mesh,
777  *        dividing cell ids in \a revDesc into groups each referring to one
778  *        cell of the result mesh the same way as \a descIndx divides \a desc.
779  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780  *        shares the node coordinates array with \a this mesh. The caller is to
781  *        delete this mesh using decrRef() as it is no more needed.
782  *  \throw If the coordinates array is not set.
783  *  \throw If the nodal connectivity of cells is node defined.
784  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785  *         revDescIndx == NULL.
786  * 
787  *  \if ENABLE_EXAMPLES
788  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
789  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
790  *  \endif
791  * \sa buildDescendingConnectivity()
792  */
793 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
794 {
795   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
796 }
797
798 /*!
799  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
800  * For speed reasons no check of this will be done. This method calls
801  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
802  * This method lists cell by cell in \b this which are its neighbors. To compute the result
803  * only connectivities are considered.
804  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
805  * The format of return is hence \ref numbering-indirect.
806  *
807  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
808  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
809  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
810  * is equal to the last values in \b neighborsIndx.
811  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
812  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
813  */
814 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
815 {
816   MCAuto<DataArrayInt> desc=DataArrayInt::New();
817   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
818   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
819   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
820   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
821   meshDM1=0;
822   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
823 }
824
825 /*!
826  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
827  * of MEDCouplingUMesh::computeNeighborsOfCells.
828  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
829  * 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 (\ref numbering-indirect) input params are
832  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
833  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
834  * are considered.
835  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836  *
837  * \param [in] desc descending connectivity array.
838  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
841  * \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
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \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.
844  */
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
847 {
848   if(!desc || !descIndx || !revDesc || !revDescIndx)
849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850   const int *descPtr=desc->getConstPointer();
851   const int *descIPtr=descIndx->getConstPointer();
852   const int *revDescPtr=revDesc->getConstPointer();
853   const int *revDescIPtr=revDescIndx->getConstPointer();
854   //
855   int nbCells=descIndx->getNumberOfTuples()-1;
856   MCAuto<DataArrayInt> out0=DataArrayInt::New();
857   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858   int *out1Ptr=out1->getPointer();
859   *out1Ptr++=0;
860   out0->reserve(desc->getNumberOfTuples());
861   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862     {
863       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864         {
865           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866           s.erase(i);
867           out0->insertAtTheEnd(s.begin(),s.end());
868         }
869       *out1Ptr=out0->getNumberOfTuples();
870     }
871   neighbors=out0.retn();
872   neighborsIndx=out1.retn();
873 }
874
875 /*!
876  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877  * For speed reasons no check of this will be done. This method calls
878  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
879  * This method lists node by node in \b this which are its neighbors. To compute the result
880  * only connectivities are considered.
881  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
882  *
883  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
884  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
885  * parameter allows to select the right part in this array (\ref numbering-indirect).
886  * The number of tuples is equal to the last values in \b neighborsIndx.
887  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
888  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
889  */
890 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
891 {
892   checkFullyDefined();
893   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
894   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
895   MCAuto<MEDCouplingUMesh> mesh1D;
896   switch(mdim)
897   {
898     case 3:
899       {
900         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
901         break;
902       }
903     case 2:
904       {
905         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
906         break;
907       }
908     case 1:
909       {
910         mesh1D=const_cast<MEDCouplingUMesh *>(this);
911         mesh1D->incrRef();
912         break;
913       }
914     default:
915       {
916         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
917       }
918   }
919   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
920   mesh1D->getReverseNodalConnectivity(desc,descIndx);
921   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
922   ret0->alloc(desc->getNumberOfTuples(),1);
923   int *r0Pt(ret0->getPointer());
924   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
925   for(int i=0;i<nbNodes;i++,rni++)
926     {
927       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
928         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
929     }
930   neighbors=ret0.retn();
931   neighborsIdx=descIndx.retn();
932 }
933
934 /// @cond INTERNAL
935
936 /*!
937  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
938  * For speed reasons no check of this will be done.
939  */
940 template<class SonsGenerator>
941 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
942 {
943   if(!desc || !descIndx || !revDesc || !revDescIndx)
944     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
945   checkConnectivityFullyDefined();
946   int nbOfCells=getNumberOfCells();
947   int nbOfNodes=getNumberOfNodes();
948   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
949   int *revNodalIndxPtr=revNodalIndx->getPointer();
950   const int *conn=_nodal_connec->getConstPointer();
951   const int *connIndex=_nodal_connec_index->getConstPointer();
952   std::string name="Mesh constituent of "; name+=getName();
953   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
954   ret->setCoords(getCoords());
955   ret->allocateCells(2*nbOfCells);
956   descIndx->alloc(nbOfCells+1,1);
957   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
958   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
959   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
960     {
961       int pos=connIndex[eltId];
962       int posP1=connIndex[eltId+1];
963       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
964       SonsGenerator sg(cm);
965       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
966       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
967       for(unsigned i=0;i<nbOfSons;i++)
968         {
969           INTERP_KERNEL::NormalizedCellType cmsId;
970           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
971           for(unsigned k=0;k<nbOfNodesSon;k++)
972             if(tmp[k]>=0)
973               revNodalIndxPtr[tmp[k]+1]++;
974           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
975           revDesc2->pushBackSilent(eltId);
976         }
977       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
978     }
979   int nbOfCellsM1=ret->getNumberOfCells();
980   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
981   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
982   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
983   int *revNodalPtr=revNodal->getPointer();
984   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
985   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
986   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
987     {
988       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
989       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
990       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
991         if(*iter>=0)//for polyhedrons
992           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
993     }
994   //
995   DataArrayInt *commonCells=0,*commonCellsI=0;
996   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
997   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
998   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
999   int newNbOfCellsM1=-1;
1000   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1001                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1002   std::vector<bool> isImpacted(nbOfCellsM1,false);
1003   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1004     for(int work2=work[0];work2!=work[1];work2++)
1005       isImpacted[commonCellsPtr[work2]]=true;
1006   const int *o2nM1Ptr=o2nM1->getConstPointer();
1007   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1008   const int *n2oM1Ptr=n2oM1->getConstPointer();
1009   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1010   ret2->copyTinyInfoFrom(this);
1011   desc->alloc(descIndx->back(),1);
1012   int *descPtr=desc->getPointer();
1013   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1014   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1015     {
1016       if(!isImpacted[i])
1017         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1018       else
1019         {
1020           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1021             {
1022               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1023               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1024             }
1025           else
1026             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1027         }
1028     }
1029   revDesc->reserve(newNbOfCellsM1);
1030   revDescIndx->alloc(newNbOfCellsM1+1,1);
1031   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1032   const int *revDesc2Ptr=revDesc2->getConstPointer();
1033   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1034     {
1035       int oldCellIdM1=n2oM1Ptr[i];
1036       if(!isImpacted[oldCellIdM1])
1037         {
1038           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1039           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1040         }
1041       else
1042         {
1043           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1044             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1045           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1046           commonCellsIPtr++;
1047         }
1048     }
1049   //
1050   return ret2.retn();
1051 }
1052
1053 struct MEDCouplingAccVisit
1054 {
1055   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1056   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1057   int _new_nb_of_nodes;
1058 };
1059
1060 /// @endcond
1061
1062 /*!
1063  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1064  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1065  * array of cell ids. Pay attention that after conversion all algorithms work slower
1066  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1067  * conversion due presence of invalid ids in the array of cells to convert, as a
1068  * result \a this mesh contains some already converted elements. In this case the 2D
1069  * mesh remains valid but 3D mesh becomes \b inconsistent!
1070  *  \warning This method can significantly modify the order of geometric types in \a this,
1071  *          hence, to write this mesh to the MED file, its cells must be sorted using
1072  *          sortCellsInMEDFileFrmt().
1073  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1074  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1075  *         cellIdsToConvertBg.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If the nodal connectivity of cells is node defined.
1078  *  \throw If dimension of \a this mesh is not either 2 or 3.
1079  *
1080  *  \if ENABLE_EXAMPLES
1081  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1082  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1083  *  \endif
1084  */
1085 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1086 {
1087   checkFullyDefined();
1088   int dim=getMeshDimension();
1089   if(dim<2 || dim>3)
1090     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1091   int nbOfCells(getNumberOfCells());
1092   if(dim==2)
1093     {
1094       const int *connIndex=_nodal_connec_index->getConstPointer();
1095       int *conn=_nodal_connec->getPointer();
1096       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1097         {
1098           if(*iter>=0 && *iter<nbOfCells)
1099             {
1100               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1101               if(!cm.isQuadratic())
1102                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1103               else
1104                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1105             }
1106           else
1107             {
1108               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1109               oss << " in range [0," << nbOfCells << ") !";
1110               throw INTERP_KERNEL::Exception(oss.str().c_str());
1111             }
1112         }
1113     }
1114   else
1115     {
1116       int *connIndex(_nodal_connec_index->getPointer());
1117       const int *connOld(_nodal_connec->getConstPointer());
1118       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1119       std::vector<bool> toBeDone(nbOfCells,false);
1120       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1121         {
1122           if(*iter>=0 && *iter<nbOfCells)
1123             toBeDone[*iter]=true;
1124           else
1125             {
1126               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1127               oss << " in range [0," << nbOfCells << ") !";
1128               throw INTERP_KERNEL::Exception(oss.str().c_str());
1129             }
1130         }
1131       for(int cellId=0;cellId<nbOfCells;cellId++)
1132         {
1133           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1134           int lgthOld(posP1-pos-1);
1135           if(toBeDone[cellId])
1136             {
1137               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1138               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1139               int *tmp(new int[nbOfFaces*lgthOld+1]);
1140               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1141               for(unsigned j=0;j<nbOfFaces;j++)
1142                 {
1143                   INTERP_KERNEL::NormalizedCellType type;
1144                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1145                   work+=offset;
1146                   *work++=-1;
1147                 }
1148               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1149               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1150               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1151               delete [] tmp;
1152             }
1153           else
1154             {
1155               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1156               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1157             }
1158         }
1159       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1160     }
1161   computeTypes();
1162 }
1163
1164 /*!
1165  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1166  * polyhedrons (if \a this is a 3D mesh).
1167  *  \warning As this method is purely for user-friendliness and no optimization is
1168  *          done to avoid construction of a useless vector, this method can be costly
1169  *          in memory.
1170  *  \throw If the coordinates array is not set.
1171  *  \throw If the nodal connectivity of cells is node defined.
1172  *  \throw If dimension of \a this mesh is not either 2 or 3.
1173  */
1174 void MEDCouplingUMesh::convertAllToPoly()
1175 {
1176   int nbOfCells=getNumberOfCells();
1177   std::vector<int> cellIds(nbOfCells);
1178   for(int i=0;i<nbOfCells;i++)
1179     cellIds[i]=i;
1180   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1181 }
1182
1183 /*!
1184  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1185  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1186  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1187  * base facet of the volume and the second half of nodes describes an opposite facet
1188  * having the same number of nodes as the base one. This method converts such
1189  * connectivity to a valid polyhedral format where connectivity of each facet is
1190  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1191  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1192  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1193  * a correct orientation of the first facet of a polyhedron, else orientation of a
1194  * corrected cell is reverse.<br>
1195  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1196  * it releases the user from boring description of polyhedra connectivity in the valid
1197  * format.
1198  *  \throw If \a this->getMeshDimension() != 3.
1199  *  \throw If \a this->getSpaceDimension() != 3.
1200  *  \throw If the nodal connectivity of cells is not defined.
1201  *  \throw If the coordinates array is not set.
1202  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1203  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1204  *
1205  *  \if ENABLE_EXAMPLES
1206  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1207  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1208  *  \endif
1209  */
1210 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1211 {
1212   checkFullyDefined();
1213   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1215   int nbOfCells=getNumberOfCells();
1216   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1217   newCi->alloc(nbOfCells+1,1);
1218   int *newci=newCi->getPointer();
1219   const int *ci=_nodal_connec_index->getConstPointer();
1220   const int *c=_nodal_connec->getConstPointer();
1221   newci[0]=0;
1222   for(int i=0;i<nbOfCells;i++)
1223     {
1224       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1225       if(type==INTERP_KERNEL::NORM_POLYHED)
1226         {
1227           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1228             {
1229               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1230               throw INTERP_KERNEL::Exception(oss.str().c_str());
1231             }
1232           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1233           if(n2%2!=0)
1234             {
1235               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 !";
1236               throw INTERP_KERNEL::Exception(oss.str().c_str());
1237             }
1238           int n1=(int)(n2/2);
1239           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)
1240         }
1241       else
1242         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1243     }
1244   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1245   newC->alloc(newci[nbOfCells],1);
1246   int *newc=newC->getPointer();
1247   for(int i=0;i<nbOfCells;i++)
1248     {
1249       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1250       if(type==INTERP_KERNEL::NORM_POLYHED)
1251         {
1252           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1253           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1254           *newc++=-1;
1255           for(std::size_t j=0;j<n1;j++)
1256             {
1257               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1258               newc[n1+5*j]=-1;
1259               newc[n1+5*j+1]=c[ci[i]+1+j];
1260               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1261               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1262               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1263             }
1264           newc+=n1*6;
1265         }
1266       else
1267         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1268     }
1269   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1270   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1271 }
1272
1273
1274 /*!
1275  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1276  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1277  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1278  *          to write this mesh to the MED file, its cells must be sorted using
1279  *          sortCellsInMEDFileFrmt().
1280  * \return \c true if at least one cell has been converted, \c false else. In the
1281  *         last case the nodal connectivity remains unchanged.
1282  * \throw If the coordinates array is not set.
1283  * \throw If the nodal connectivity of cells is not defined.
1284  * \throw If \a this->getMeshDimension() < 0.
1285  */
1286 bool MEDCouplingUMesh::unPolyze()
1287 {
1288   checkFullyDefined();
1289   int mdim=getMeshDimension();
1290   if(mdim<0)
1291     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1292   if(mdim<=1)
1293     return false;
1294   int nbOfCells=getNumberOfCells();
1295   if(nbOfCells<1)
1296     return false;
1297   int initMeshLgth=getNodalConnectivityArrayLen();
1298   int *conn=_nodal_connec->getPointer();
1299   int *index=_nodal_connec_index->getPointer();
1300   int posOfCurCell=0;
1301   int newPos=0;
1302   int lgthOfCurCell;
1303   bool ret=false;
1304   for(int i=0;i<nbOfCells;i++)
1305     {
1306       lgthOfCurCell=index[i+1]-posOfCurCell;
1307       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1308       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1309       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1310       int newLgth;
1311       if(cm.isDynamic())
1312         {
1313           switch(cm.getDimension())
1314           {
1315             case 2:
1316               {
1317                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1318                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1319                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1320                 break;
1321               }
1322             case 3:
1323               {
1324                 int nbOfFaces,lgthOfPolyhConn;
1325                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1326                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1327                 break;
1328               }
1329             case 1:
1330               {
1331                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1332                 break;
1333               }
1334           }
1335           ret=ret || (newType!=type);
1336           conn[newPos]=newType;
1337           newPos+=newLgth+1;
1338           posOfCurCell=index[i+1];
1339           index[i+1]=newPos;
1340         }
1341       else
1342         {
1343           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1344           newPos+=lgthOfCurCell;
1345           posOfCurCell+=lgthOfCurCell;
1346           index[i+1]=newPos;
1347         }
1348     }
1349   if(newPos!=initMeshLgth)
1350     _nodal_connec->reAlloc(newPos);
1351   if(ret)
1352     computeTypes();
1353   return ret;
1354 }
1355
1356 /*!
1357  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1358  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1359  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1360  *
1361  * \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 
1362  *             precision.
1363  */
1364 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1365 {
1366   checkFullyDefined();
1367   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1369   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1370   coords->recenterForMaxPrecision(eps);
1371   //
1372   int nbOfCells=getNumberOfCells();
1373   const int *conn=_nodal_connec->getConstPointer();
1374   const int *index=_nodal_connec_index->getConstPointer();
1375   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1376   connINew->alloc(nbOfCells+1,1);
1377   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1378   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1379   bool changed=false;
1380   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1381     {
1382       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1383         {
1384           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1385           changed=true;
1386         }
1387       else
1388         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1389       *connINewPtr=connNew->getNumberOfTuples();
1390     }
1391   if(changed)
1392     setConnectivity(connNew,connINew,false);
1393 }
1394
1395 /*!
1396  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1397  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1398  * the format of the returned DataArrayInt instance.
1399  * 
1400  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1401  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1402  */
1403 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1404 {
1405   checkConnectivityFullyDefined();
1406   int nbOfCells=getNumberOfCells();
1407   const int *connIndex=_nodal_connec_index->getConstPointer();
1408   const int *conn=_nodal_connec->getConstPointer();
1409   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1410   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1411   std::vector<bool> retS(maxElt,false);
1412   for(int i=0;i<nbOfCells;i++)
1413     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1414       if(conn[j]>=0)
1415         retS[conn[j]]=true;
1416   int sz=0;
1417   for(int i=0;i<maxElt;i++)
1418     if(retS[i])
1419       sz++;
1420   DataArrayInt *ret=DataArrayInt::New();
1421   ret->alloc(sz,1);
1422   int *retPtr=ret->getPointer();
1423   for(int i=0;i<maxElt;i++)
1424     if(retS[i])
1425       *retPtr++=i;
1426   return ret;
1427 }
1428
1429 /*!
1430  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1431  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1432  */
1433 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1434 {
1435   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1436   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1437   for(int i=0;i<nbOfCells;i++)
1438     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1439       if(conn[j]>=0)
1440         {
1441           if(conn[j]<nbOfNodes)
1442             nodeIdsInUse[conn[j]]=true;
1443           else
1444             {
1445               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1446               throw INTERP_KERNEL::Exception(oss.str().c_str());
1447             }
1448         }
1449 }
1450
1451 /*!
1452  * Finds nodes not used in any cell and returns an array giving a new id to every node
1453  * by excluding the unused nodes, for which the array holds -1. The result array is
1454  * a mapping in "Old to New" mode. 
1455  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1456  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1457  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1458  *          if the node is unused or a new id else. The caller is to delete this
1459  *          array using decrRef() as it is no more needed.  
1460  *  \throw If the coordinates array is not set.
1461  *  \throw If the nodal connectivity of cells is not defined.
1462  *  \throw If the nodal connectivity includes an invalid id.
1463  *
1464  *  \if ENABLE_EXAMPLES
1465  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1466  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1467  *  \endif
1468  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1469  */
1470 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1471 {
1472   nbrOfNodesInUse=-1;
1473   int nbOfNodes(getNumberOfNodes());
1474   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1475   ret->alloc(nbOfNodes,1);
1476   int *traducer=ret->getPointer();
1477   std::fill(traducer,traducer+nbOfNodes,-1);
1478   int nbOfCells=getNumberOfCells();
1479   const int *connIndex=_nodal_connec_index->getConstPointer();
1480   const int *conn=_nodal_connec->getConstPointer();
1481   for(int i=0;i<nbOfCells;i++)
1482     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1483       if(conn[j]>=0)
1484         {
1485           if(conn[j]<nbOfNodes)
1486             traducer[conn[j]]=1;
1487           else
1488             {
1489               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1490               throw INTERP_KERNEL::Exception(oss.str().c_str());
1491             }
1492         }
1493   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1494   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1495   return ret.retn();
1496 }
1497
1498 /*!
1499  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1500  * For each cell in \b this the number of nodes constituting cell is computed.
1501  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1502  * So for pohyhedrons some nodes can be counted several times in the returned result.
1503  * 
1504  * \return a newly allocated array
1505  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1506  */
1507 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1508 {
1509   checkConnectivityFullyDefined();
1510   int nbOfCells=getNumberOfCells();
1511   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1512   ret->alloc(nbOfCells,1);
1513   int *retPtr=ret->getPointer();
1514   const int *conn=getNodalConnectivity()->getConstPointer();
1515   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1516   for(int i=0;i<nbOfCells;i++,retPtr++)
1517     {
1518       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1519         *retPtr=connI[i+1]-connI[i]-1;
1520       else
1521         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1522     }
1523   return ret.retn();
1524 }
1525
1526 /*!
1527  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1528  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1529  *
1530  * \return DataArrayInt * - new object to be deallocated by the caller.
1531  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1532  */
1533 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1534 {
1535   checkConnectivityFullyDefined();
1536   int nbOfCells=getNumberOfCells();
1537   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1538   ret->alloc(nbOfCells,1);
1539   int *retPtr=ret->getPointer();
1540   const int *conn=getNodalConnectivity()->getConstPointer();
1541   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1542   for(int i=0;i<nbOfCells;i++,retPtr++)
1543     {
1544       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1545       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1546         *retPtr=(int)s.size();
1547       else
1548         {
1549           s.erase(-1);
1550           *retPtr=(int)s.size();
1551         }
1552     }
1553   return ret.retn();
1554 }
1555
1556 /*!
1557  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1558  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1559  * 
1560  * \return a newly allocated array
1561  */
1562 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1563 {
1564   checkConnectivityFullyDefined();
1565   int nbOfCells=getNumberOfCells();
1566   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1567   ret->alloc(nbOfCells,1);
1568   int *retPtr=ret->getPointer();
1569   const int *conn=getNodalConnectivity()->getConstPointer();
1570   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1571   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1572     {
1573       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1574       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1575     }
1576   return ret.retn();
1577 }
1578
1579 /*!
1580  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1581  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1582  * array mean that the corresponding old node is no more used. 
1583  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1584  *           this->getNumberOfNodes() before call of this method. The caller is to
1585  *           delete this array using decrRef() as it is no more needed. 
1586  *  \throw If the coordinates array is not set.
1587  *  \throw If the nodal connectivity of cells is not defined.
1588  *  \throw If the nodal connectivity includes an invalid id.
1589  *  \sa areAllNodesFetched
1590  *
1591  *  \if ENABLE_EXAMPLES
1592  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1593  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1594  *  \endif
1595  */
1596 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1597 {
1598   return MEDCouplingPointSet::zipCoordsTraducer();
1599 }
1600
1601 /*!
1602  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1603  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1604  */
1605 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1606 {
1607   switch(compType)
1608   {
1609     case 0:
1610       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1611     case 1:
1612       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1613     case 2:
1614       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1615     case 3:
1616       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1617     case 7:
1618       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1619   }
1620   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1621 }
1622
1623 /*!
1624  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1625  */
1626 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1627 {
1628   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1629     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1630   return 0;
1631 }
1632
1633 /*!
1634  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1635  */
1636 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1637 {
1638   int sz=connI[cell1+1]-connI[cell1];
1639   if(sz==connI[cell2+1]-connI[cell2])
1640     {
1641       if(conn[connI[cell1]]==conn[connI[cell2]])
1642         {
1643           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1644           unsigned dim=cm.getDimension();
1645           if(dim!=3)
1646             {
1647               if(dim!=1)
1648                 {
1649                   int sz1=2*(sz-1);
1650                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1651                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1652                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1653                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1654                   return work!=tmp+sz1?1:0;
1655                 }
1656               else
1657                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1658             }
1659           else
1660             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1661         }
1662     }
1663   return 0;
1664 }
1665
1666 /*!
1667  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1668  */
1669 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1670 {
1671   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1672     {
1673       if(conn[connI[cell1]]==conn[connI[cell2]])
1674         {
1675           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1676           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1677           return s1==s2?1:0;
1678         }
1679     }
1680   return 0;
1681 }
1682
1683 /*!
1684  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1685  */
1686 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1687 {
1688   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1689     {
1690       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1691       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1692       return s1==s2?1:0;
1693     }
1694   return 0;
1695 }
1696
1697 /*!
1698  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1699  */
1700 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1701 {
1702   int sz=connI[cell1+1]-connI[cell1];
1703   if(sz==connI[cell2+1]-connI[cell2])
1704     {
1705       if(conn[connI[cell1]]==conn[connI[cell2]])
1706         {
1707           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1708           unsigned dim=cm.getDimension();
1709           if(dim!=3)
1710             {
1711               if(dim!=1)
1712                 {
1713                   int sz1=2*(sz-1);
1714                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1715                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1716                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1717                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1718                   if(work!=tmp+sz1)
1719                     return 1;
1720                   else
1721                     {
1722                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1723                       std::reverse_iterator<int *> it2((int *)tmp);
1724                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1725                         return 2;
1726                       else
1727                         return 0;
1728                     }
1729
1730                   return work!=tmp+sz1?1:0;
1731                 }
1732               else
1733                 {//case of SEG2 and SEG3
1734                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1735                     return 1;
1736                   if(!cm.isQuadratic())
1737                     {
1738                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1739                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1740                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1741                         return 2;
1742                       return 0;
1743                     }
1744                   else
1745                     {
1746                       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])
1747                         return 2;
1748                       return 0;
1749                     }
1750                 }
1751             }
1752           else
1753             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1754         }
1755     }
1756   return 0;
1757 }
1758
1759 /*!
1760  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1761  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1762  * and result remains unchanged.
1763  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1764  * If in 'candidates' pool -1 value is considered as an empty value.
1765  * WARNING this method returns only ONE set of result !
1766  */
1767 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1768 {
1769   if(candidates.size()<1)
1770     return false;
1771   bool ret=false;
1772   std::vector<int>::const_iterator iter=candidates.begin();
1773   int start=(*iter++);
1774   for(;iter!=candidates.end();iter++)
1775     {
1776       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1777       if(status!=0)
1778         {
1779           if(!ret)
1780             {
1781               result->pushBackSilent(start);
1782               ret=true;
1783             }
1784           if(status==1)
1785             result->pushBackSilent(*iter);
1786           else
1787             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1788         }
1789     }
1790   return ret;
1791 }
1792
1793 /*!
1794  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1795  * by \a compType.
1796  * This method keeps the coordiantes of \a this. This method is time consuming.
1797  *
1798  * \param [in] compType input specifying the technique used to compare cells each other.
1799  *   - 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.
1800  *   - 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)
1801  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1802  *   - 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
1803  * can be used for users not sensitive to orientation of cell
1804  * \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.
1805  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1806  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1807  * \return the correspondance array old to new in a newly allocated array.
1808  * 
1809  */
1810 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1811 {
1812   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1813   getReverseNodalConnectivity(revNodal,revNodalI);
1814   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1815 }
1816
1817 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1818                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1819 {
1820   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1821   int nbOfCells=nodalI->getNumberOfTuples()-1;
1822   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1823   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1824   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1825   std::vector<bool> isFetched(nbOfCells,false);
1826   if(startCellId==0)
1827     {
1828       for(int i=0;i<nbOfCells;i++)
1829         {
1830           if(!isFetched[i])
1831             {
1832               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1833               std::vector<int> v,v2;
1834               if(connOfNode!=connPtr+connIPtr[i+1])
1835                 {
1836                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1837                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1838                   connOfNode++;
1839                 }
1840               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1841                 if(*connOfNode>=0)
1842                   {
1843                     v=v2;
1844                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1845                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1846                     v2.resize(std::distance(v2.begin(),it));
1847                   }
1848               if(v2.size()>1)
1849                 {
1850                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1851                     {
1852                       int pos=commonCellsI->back();
1853                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1854                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1855                         isFetched[*it]=true;
1856                     }
1857                 }
1858             }
1859         }
1860     }
1861   else
1862     {
1863       for(int i=startCellId;i<nbOfCells;i++)
1864         {
1865           if(!isFetched[i])
1866             {
1867               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1868               std::vector<int> v,v2;
1869               if(connOfNode!=connPtr+connIPtr[i+1])
1870                 {
1871                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1872                   connOfNode++;
1873                 }
1874               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1875                 if(*connOfNode>=0)
1876                   {
1877                     v=v2;
1878                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1879                     v2.resize(std::distance(v2.begin(),it));
1880                   }
1881               if(v2.size()>1)
1882                 {
1883                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1884                     {
1885                       int pos=commonCellsI->back();
1886                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1887                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1888                         isFetched[*it]=true;
1889                     }
1890                 }
1891             }
1892         }
1893     }
1894   commonCellsArr=commonCells.retn();
1895   commonCellsIArr=commonCellsI.retn();
1896 }
1897
1898 /*!
1899  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1900  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1901  * than \a other->getNumberOfCells() in the returned array means that there is no
1902  * corresponding cell in \a this mesh.
1903  * It is expected that \a this and \a other meshes share the same node coordinates
1904  * array, if it is not so an exception is thrown. 
1905  *  \param [in] other - the mesh to compare with.
1906  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1907  *         valid values [0,1,2], see zipConnectivityTraducer().
1908  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1909  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1910  *         values. The caller is to delete this array using
1911  *         decrRef() as it is no more needed.
1912  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1913  *         mesh.
1914  *
1915  *  \if ENABLE_EXAMPLES
1916  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1917  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1918  *  \endif
1919  *  \sa checkDeepEquivalOnSameNodesWith()
1920  *  \sa checkGeoEquivalWith()
1921  */
1922 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1923 {
1924   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1925   int nbOfCells=getNumberOfCells();
1926   static const int possibleCompType[]={0,1,2};
1927   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1928     {
1929       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1930       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1931       oss << " !";
1932       throw INTERP_KERNEL::Exception(oss.str().c_str());
1933     }
1934   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1935   arr=o2n->subArray(nbOfCells);
1936   arr->setName(other->getName());
1937   int tmp;
1938   if(other->getNumberOfCells()==0)
1939     return true;
1940   return arr->getMaxValue(tmp)<nbOfCells;
1941 }
1942
1943 /*!
1944  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1945  * This method tries to determine if \b other is fully included in \b this.
1946  * The main difference is that this method is not expected to throw exception.
1947  * This method has two outputs :
1948  *
1949  * \param other other mesh
1950  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1951  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1952  */
1953 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1954 {
1955   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1956   DataArrayInt *commonCells=0,*commonCellsI=0;
1957   int thisNbCells=getNumberOfCells();
1958   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1959   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1960   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1961   int otherNbCells=other->getNumberOfCells();
1962   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1963   arr2->alloc(otherNbCells,1);
1964   arr2->fillWithZero();
1965   int *arr2Ptr=arr2->getPointer();
1966   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1967   for(int i=0;i<nbOfCommon;i++)
1968     {
1969       int start=commonCellsPtr[commonCellsIPtr[i]];
1970       if(start<thisNbCells)
1971         {
1972           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1973             {
1974               int sig=commonCellsPtr[j]>0?1:-1;
1975               int val=std::abs(commonCellsPtr[j])-1;
1976               if(val>=thisNbCells)
1977                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1978             }
1979         }
1980     }
1981   arr2->setName(other->getName());
1982   if(arr2->presenceOfValue(0))
1983     return false;
1984   arr=arr2.retn();
1985   return true;
1986 }
1987
1988 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1989 {
1990   if(!other)
1991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1992   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1993   if(!otherC)
1994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1995   std::vector<const MEDCouplingUMesh *> ms(2);
1996   ms[0]=this;
1997   ms[1]=otherC;
1998   return MergeUMeshesOnSameCoords(ms);
1999 }
2000
2001 /*!
2002  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2003  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2004  * cellIds is not given explicitely but by a range python like.
2005  * 
2006  * \param start
2007  * \param end
2008  * \param step
2009  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2010  * \return a newly allocated
2011  * 
2012  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2013  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2014  */
2015 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2016 {
2017   if(getMeshDimension()!=-1)
2018     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2019   else
2020     {
2021       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2022       if(newNbOfCells!=1)
2023         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2024       if(start!=0)
2025         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2026       incrRef();
2027       return const_cast<MEDCouplingUMesh *>(this);
2028     }
2029 }
2030
2031 /*!
2032  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2033  * The result mesh shares or not the node coordinates array with \a this mesh depending
2034  * on \a keepCoords parameter.
2035  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2036  *           to write this mesh to the MED file, its cells must be sorted using
2037  *           sortCellsInMEDFileFrmt().
2038  *  \param [in] begin - an array of cell ids to include to the new mesh.
2039  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2040  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2041  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2042  *         by calling zipCoords().
2043  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2044  *         to delete this mesh using decrRef() as it is no more needed. 
2045  *  \throw If the coordinates array is not set.
2046  *  \throw If the nodal connectivity of cells is not defined.
2047  *  \throw If any cell id in the array \a begin is not valid.
2048  *
2049  *  \if ENABLE_EXAMPLES
2050  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2051  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2052  *  \endif
2053  */
2054 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2055 {
2056   if(getMeshDimension()!=-1)
2057     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2058   else
2059     {
2060       if(end-begin!=1)
2061         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2062       if(begin[0]!=0)
2063         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2064       incrRef();
2065       return const_cast<MEDCouplingUMesh *>(this);
2066     }
2067 }
2068
2069 /*!
2070  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2071  *
2072  * 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.
2073  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2074  * The number of cells of \b this will remain the same with this method.
2075  *
2076  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2077  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2078  * \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 ).
2079  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2080  */
2081 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2082 {
2083   checkConnectivityFullyDefined();
2084   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2085   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2087   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2088     {
2089       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2090       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2091       throw INTERP_KERNEL::Exception(oss.str().c_str());
2092     }
2093   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2094   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2095     {
2096       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2097       throw INTERP_KERNEL::Exception(oss.str().c_str());
2098     }
2099   int nbOfCells=getNumberOfCells();
2100   bool easyAssign=true;
2101   const int *connI=_nodal_connec_index->getConstPointer();
2102   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2103   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2104     {
2105       if(*it>=0 && *it<nbOfCells)
2106         {
2107           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2108         }
2109       else
2110         {
2111           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2112           throw INTERP_KERNEL::Exception(oss.str().c_str());
2113         }
2114     }
2115   if(easyAssign)
2116     {
2117       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2118       computeTypes();
2119     }
2120   else
2121     {
2122       DataArrayInt *arrOut=0,*arrIOut=0;
2123       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2124                                                arrOut,arrIOut);
2125       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2126       setConnectivity(arrOut,arrIOut,true);
2127     }
2128 }
2129
2130 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2131 {
2132   checkConnectivityFullyDefined();
2133   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2134   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2135     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2136   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2137     {
2138       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2139       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2140       throw INTERP_KERNEL::Exception(oss.str().c_str());
2141     }
2142   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2143   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2144     {
2145       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2146       throw INTERP_KERNEL::Exception(oss.str().c_str());
2147     }
2148   int nbOfCells=getNumberOfCells();
2149   bool easyAssign=true;
2150   const int *connI=_nodal_connec_index->getConstPointer();
2151   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2152   int it=start;
2153   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2154     {
2155       if(it>=0 && it<nbOfCells)
2156         {
2157           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2158         }
2159       else
2160         {
2161           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2162           throw INTERP_KERNEL::Exception(oss.str().c_str());
2163         }
2164     }
2165   if(easyAssign)
2166     {
2167       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2168       computeTypes();
2169     }
2170   else
2171     {
2172       DataArrayInt *arrOut=0,*arrIOut=0;
2173       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2174                                                 arrOut,arrIOut);
2175       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2176       setConnectivity(arrOut,arrIOut,true);
2177     }
2178 }                      
2179
2180 /*!
2181  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2182  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2183  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2184  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2185  *
2186  * \param [in] begin input start of array of node ids.
2187  * \param [in] end input end of array of node ids.
2188  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2189  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2190  */
2191 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2192 {
2193   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2194   checkConnectivityFullyDefined();
2195   int tmp=-1;
2196   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2197   std::vector<bool> fastFinder(sz,false);
2198   for(const int *work=begin;work!=end;work++)
2199     if(*work>=0 && *work<sz)
2200       fastFinder[*work]=true;
2201   int nbOfCells=getNumberOfCells();
2202   const int *conn=getNodalConnectivity()->getConstPointer();
2203   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2204   for(int i=0;i<nbOfCells;i++)
2205     {
2206       int ref=0,nbOfHit=0;
2207       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2208         if(*work2>=0)
2209           {
2210             ref++;
2211             if(fastFinder[*work2])
2212               nbOfHit++;
2213           }
2214       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2215         cellIdsKept->pushBackSilent(i);
2216     }
2217   cellIdsKeptArr=cellIdsKept.retn();
2218 }
2219
2220 /*!
2221  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2222  * this->getMeshDimension(), that bound some cells of \a this mesh.
2223  * The cells of lower dimension to include to the result mesh are selected basing on
2224  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2225  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2226  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2227  * created mesh shares the node coordinates array with \a this mesh. 
2228  *  \param [in] begin - the array of node ids.
2229  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2230  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2231  *         array \a begin are added, else cells whose any node is in the
2232  *         array \a begin are added.
2233  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2234  *         to delete this mesh using decrRef() as it is no more needed. 
2235  *  \throw If the coordinates array is not set.
2236  *  \throw If the nodal connectivity of cells is not defined.
2237  *  \throw If any node id in \a begin is not valid.
2238  *
2239  *  \if ENABLE_EXAMPLES
2240  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2241  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2242  *  \endif
2243  */
2244 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2245 {
2246   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2247   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2248   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2249   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2250   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2251 }
2252
2253 /*!
2254  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2255  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2256  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2257  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2258  *         by calling zipCoords().
2259  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2260  *         to delete this mesh using decrRef() as it is no more needed. 
2261  *  \throw If the coordinates array is not set.
2262  *  \throw If the nodal connectivity of cells is not defined.
2263  *
2264  *  \if ENABLE_EXAMPLES
2265  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2266  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2267  *  \endif
2268  */
2269 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2270 {
2271   DataArrayInt *desc=DataArrayInt::New();
2272   DataArrayInt *descIndx=DataArrayInt::New();
2273   DataArrayInt *revDesc=DataArrayInt::New();
2274   DataArrayInt *revDescIndx=DataArrayInt::New();
2275   //
2276   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277   revDesc->decrRef();
2278   desc->decrRef();
2279   descIndx->decrRef();
2280   int nbOfCells=meshDM1->getNumberOfCells();
2281   const int *revDescIndxC=revDescIndx->getConstPointer();
2282   std::vector<int> boundaryCells;
2283   for(int i=0;i<nbOfCells;i++)
2284     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2285       boundaryCells.push_back(i);
2286   revDescIndx->decrRef();
2287   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2288   return ret;
2289 }
2290
2291 /*!
2292  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2293  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2294  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2295  */
2296 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2297 {
2298   checkFullyDefined();
2299   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2300   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2301   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2302   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2303   //
2304   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2305   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2306   //
2307   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2308   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2309   const int *revDescPtr=revDesc->getConstPointer();
2310   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2311   int nbOfCells=getNumberOfCells();
2312   std::vector<bool> ret1(nbOfCells,false);
2313   int sz=0;
2314   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2315     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2316       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2317   //
2318   DataArrayInt *ret2=DataArrayInt::New();
2319   ret2->alloc(sz,1);
2320   int *ret2Ptr=ret2->getPointer();
2321   sz=0;
2322   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2323     if(*it)
2324       *ret2Ptr++=sz;
2325   ret2->setName("BoundaryCells");
2326   return ret2;
2327 }
2328
2329 /*!
2330  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2331  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2332  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2333  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2334  *
2335  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2336  * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2337  * equals a cell in \b otherDimM1OnSameCoords.
2338  *
2339  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2341  *
2342  * \param [in] otherDimM1OnSameCoords
2343  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2344  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2345  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2346  */
2347 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2348 {
2349   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2351   checkConnectivityFullyDefined();
2352   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2353   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2355   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2356   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2357   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2358   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2359   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2360   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2361   DataArrayInt *idsOtherInConsti=0;
2362   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2363   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2364   if(!b)
2365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2366   std::set<int> s1;
2367   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2368     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2369   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2370   s1arr_renum1->sort();
2371   cellIdsRk0=s0arr.retn();
2372   //cellIdsRk1=s_renum1.retn();
2373   cellIdsRk1=s1arr_renum1.retn();
2374 }
2375
2376 /*!
2377  * 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
2378  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2379  * 
2380  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2381  */
2382 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2383 {
2384   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2385   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2386   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2387   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2388   //
2389   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2390   revDesc=0; desc=0; descIndx=0;
2391   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2392   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2393   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2394 }
2395
2396 /*!
2397  * Finds nodes lying on the boundary of \a this mesh.
2398  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2399  *          nodes. The caller is to delete this array using decrRef() as it is no
2400  *          more needed.
2401  *  \throw If the coordinates array is not set.
2402  *  \throw If the nodal connectivity of cells is node defined.
2403  *
2404  *  \if ENABLE_EXAMPLES
2405  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2406  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2407  *  \endif
2408  */
2409 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2410 {
2411   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2412   return skin->computeFetchedNodeIds();
2413 }
2414
2415 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2416 {
2417   incrRef();
2418   return const_cast<MEDCouplingUMesh *>(this);
2419 }
2420
2421 /*!
2422  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2423  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2424  * 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.
2425  * 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.
2426  * 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.
2427  *
2428  * \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
2429  *             parameter is altered during the call.
2430  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2431  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2432  * \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.
2433  *
2434  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2435  */
2436 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2437                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2438 {
2439   typedef MCAuto<DataArrayInt> DAInt;
2440
2441   checkFullyDefined();
2442   otherDimM1OnSameCoords.checkFullyDefined();
2443   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2444     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2445   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2447   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2448   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2449   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2450   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2451   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2452   MCAuto<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2453   DAInt s1=m0Part->computeFetchedNodeIds();
2454   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2455   DAInt s3=s2->buildSubstraction(s1);
2456   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2457   //
2458   MCAuto<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2459   int nCells2 = m0Part2->getNumberOfCells();
2460   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2461   MCAuto<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2462   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2463   DataArrayInt *tmp00=0,*tmp11=0;
2464   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2465   DAInt neighInit00(tmp00);
2466   DAInt neighIInit00(tmp11);
2467   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2468   DataArrayInt *idsTmp=0;
2469   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2470   DAInt ids(idsTmp);
2471   if(!b)
2472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2473   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2474   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2475   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2476   DataArrayInt *tmp0=0,*tmp1=0;
2477   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2478   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2479   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2480   DAInt neigh00(tmp0);
2481   DAInt neighI00(tmp1);
2482
2483   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2484   int seed = 0, nIter = 0;
2485   int nIterMax = nCells2+1; // Safety net for the loop
2486   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2487   hitCells->fillWithValue(-1);
2488   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2489   cellsToModifyConn0_torenum->alloc(0,1);
2490   while (nIter < nIterMax)
2491     {
2492       DAInt t = hitCells->findIdsEqual(-1);
2493       if (!t->getNumberOfTuples())
2494         break;
2495       // Connex zone without the crack (to compute the next seed really)
2496       int dnu;
2497       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2498       int cnt = 0;
2499       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2500         hitCells->setIJ(*ptr,0,1);
2501       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2502       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2503       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2504       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2505       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2506       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2507       DAInt intersec = nonHitCells->buildIntersection(comple);
2508       if (intersec->getNumberOfTuples())
2509         { seed = intersec->getIJ(0,0); }
2510       else
2511         { break; }
2512       nIter++;
2513     }
2514   if (nIter >= nIterMax)
2515     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2516
2517   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2518   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2519   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2520   //
2521   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2522   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2523   nodeIdsToDuplicate=s3.retn();
2524 }
2525
2526 /*!
2527  * This method operates a modification of the connectivity and coords in \b this.
2528  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2529  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2530  * 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
2531  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2532  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2533  * 
2534  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2535  * 
2536  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2537  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2538  */
2539 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2540 {
2541   int nbOfNodes=getNumberOfNodes();
2542   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2543   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2544 }
2545
2546 /*!
2547  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2548  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2549  *
2550  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2551  *
2552  * \sa renumberNodesInConn
2553  */
2554 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2555 {
2556   checkConnectivityFullyDefined();
2557   int *conn(getNodalConnectivity()->getPointer());
2558   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2559   int nbOfCells(getNumberOfCells());
2560   for(int i=0;i<nbOfCells;i++)
2561     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2562       {
2563         int& node=conn[iconn];
2564         if(node>=0)//avoid polyhedron separator
2565           {
2566             node+=offset;
2567           }
2568       }
2569   _nodal_connec->declareAsNew();
2570   updateTime();
2571 }
2572
2573 /*!
2574  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2575  *  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
2576  *  of a big mesh.
2577  */
2578 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2579 {
2580   checkConnectivityFullyDefined();
2581   int *conn(getNodalConnectivity()->getPointer());
2582   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2583   int nbOfCells(getNumberOfCells());
2584   for(int i=0;i<nbOfCells;i++)
2585     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2586       {
2587         int& node=conn[iconn];
2588         if(node>=0)//avoid polyhedron separator
2589           {
2590             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2591             if(it!=newNodeNumbersO2N.end())
2592               {
2593                 node=(*it).second;
2594               }
2595             else
2596               {
2597                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2598                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2599               }
2600           }
2601       }
2602   _nodal_connec->declareAsNew();
2603   updateTime();
2604 }
2605
2606 /*!
2607  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2608  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2609  * This method is a generalization of shiftNodeNumbersInConn().
2610  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2611  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2612  *         this->getNumberOfNodes(), in "Old to New" mode. 
2613  *         See \ref numbering for more info on renumbering modes.
2614  *  \throw If the nodal connectivity of cells is not defined.
2615  *
2616  *  \if ENABLE_EXAMPLES
2617  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2618  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2619  *  \endif
2620  */
2621 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2622 {
2623   checkConnectivityFullyDefined();
2624   int *conn=getNodalConnectivity()->getPointer();
2625   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2626   int nbOfCells(getNumberOfCells());
2627   for(int i=0;i<nbOfCells;i++)
2628     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2629       {
2630         int& node=conn[iconn];
2631         if(node>=0)//avoid polyhedron separator
2632           {
2633             node=newNodeNumbersO2N[node];
2634           }
2635       }
2636   _nodal_connec->declareAsNew();
2637   updateTime();
2638 }
2639
2640 /*!
2641  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2642  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2643  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2644  * 
2645  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2646  */
2647 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2648 {
2649   checkConnectivityFullyDefined();
2650   int *conn=getNodalConnectivity()->getPointer();
2651   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2652   int nbOfCells=getNumberOfCells();
2653   for(int i=0;i<nbOfCells;i++)
2654     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2655       {
2656         int& node=conn[iconn];
2657         if(node>=0)//avoid polyhedron separator
2658           {
2659             node+=delta;
2660           }
2661       }
2662   _nodal_connec->declareAsNew();
2663   updateTime();
2664 }
2665
2666 /*!
2667  * This method operates a modification of the connectivity in \b this.
2668  * 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.
2669  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2670  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2671  * 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
2672  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2673  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2674  * 
2675  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2676  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2677  * 
2678  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2679  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2680  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2681  */
2682 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2683 {
2684   checkConnectivityFullyDefined();
2685   std::map<int,int> m;
2686   int val=offset;
2687   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2688     m[*work]=val;
2689   int *conn=getNodalConnectivity()->getPointer();
2690   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2691   int nbOfCells=getNumberOfCells();
2692   for(int i=0;i<nbOfCells;i++)
2693     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2694       {
2695         int& node=conn[iconn];
2696         if(node>=0)//avoid polyhedron separator
2697           {
2698             std::map<int,int>::iterator it=m.find(node);
2699             if(it!=m.end())
2700               node=(*it).second;
2701           }
2702       }
2703   updateTime();
2704 }
2705
2706 /*!
2707  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2708  *
2709  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2710  * After the call of this method the number of cells remains the same as before.
2711  *
2712  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2713  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2714  * be strictly in [0;this->getNumberOfCells()).
2715  *
2716  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2717  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2718  * should be contained in[0;this->getNumberOfCells()).
2719  * 
2720  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2721  * \param check
2722  */
2723 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2724 {
2725   checkConnectivityFullyDefined();
2726   int nbCells=getNumberOfCells();
2727   const int *array=old2NewBg;
2728   if(check)
2729     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2730   //
2731   const int *conn=_nodal_connec->getConstPointer();
2732   const int *connI=_nodal_connec_index->getConstPointer();
2733   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2734   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2735   const int *n2oPtr=n2o->begin();
2736   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2737   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2738   newConn->copyStringInfoFrom(*_nodal_connec);
2739   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2740   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2741   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2742   //
2743   int *newC=newConn->getPointer();
2744   int *newCI=newConnI->getPointer();
2745   int loc=0;
2746   newCI[0]=loc;
2747   for(int i=0;i<nbCells;i++)
2748     {
2749       int pos=n2oPtr[i];
2750       int nbOfElts=connI[pos+1]-connI[pos];
2751       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2752       loc+=nbOfElts;
2753       newCI[i+1]=loc;
2754     }
2755   //
2756   setConnectivity(newConn,newConnI);
2757   if(check)
2758     free(const_cast<int *>(array));
2759 }
2760
2761 /*!
2762  * Finds cells whose bounding boxes intersect a given bounding box.
2763  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2764  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2765  *         zMax (if in 3D). 
2766  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2767  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2768  *         extent of the bounding box of cell to produce an addition to this bounding box.
2769  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2770  *         cells. The caller is to delete this array using decrRef() as it is no more
2771  *         needed. 
2772  *  \throw If the coordinates array is not set.
2773  *  \throw If the nodal connectivity of cells is not defined.
2774  *
2775  *  \if ENABLE_EXAMPLES
2776  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2777  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2778  *  \endif
2779  */
2780 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2781 {
2782   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2783   if(getMeshDimension()==-1)
2784     {
2785       elems->pushBackSilent(0);
2786       return elems.retn();
2787     }
2788   int dim=getSpaceDimension();
2789   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2790   const int* conn      = getNodalConnectivity()->getConstPointer();
2791   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2792   const double* coords = getCoords()->getConstPointer();
2793   int nbOfCells=getNumberOfCells();
2794   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2795     {
2796       for (int i=0; i<dim; i++)
2797         {
2798           elem_bb[i*2]=std::numeric_limits<double>::max();
2799           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2800         }
2801
2802       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2803         {
2804           int node= conn[inode];
2805           if(node>=0)//avoid polyhedron separator
2806             {
2807               for (int idim=0; idim<dim; idim++)
2808                 {
2809                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2810                     {
2811                       elem_bb[idim*2] = coords[node*dim+idim] ;
2812                     }
2813                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2814                     {
2815                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2816                     }
2817                 }
2818             }
2819         }
2820       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2821         elems->pushBackSilent(ielem);
2822     }
2823   return elems.retn();
2824 }
2825
2826 /*!
2827  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2828  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2829  * added in 'elems' parameter.
2830  */
2831 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2832 {
2833   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2834   if(getMeshDimension()==-1)
2835     {
2836       elems->pushBackSilent(0);
2837       return elems.retn();
2838     }
2839   int dim=getSpaceDimension();
2840   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2841   const int* conn      = getNodalConnectivity()->getConstPointer();
2842   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2843   const double* coords = getCoords()->getConstPointer();
2844   int nbOfCells=getNumberOfCells();
2845   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2846     {
2847       for (int i=0; i<dim; i++)
2848         {
2849           elem_bb[i*2]=std::numeric_limits<double>::max();
2850           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2851         }
2852
2853       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2854         {
2855           int node= conn[inode];
2856           if(node>=0)//avoid polyhedron separator
2857             {
2858               for (int idim=0; idim<dim; idim++)
2859                 {
2860                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2861                     {
2862                       elem_bb[idim*2] = coords[node*dim+idim] ;
2863                     }
2864                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2865                     {
2866                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2867                     }
2868                 }
2869             }
2870         }
2871       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2872         elems->pushBackSilent(ielem);
2873     }
2874   return elems.retn();
2875 }
2876
2877 /*!
2878  * Returns a type of a cell by its id.
2879  *  \param [in] cellId - the id of the cell of interest.
2880  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2881  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2882  */
2883 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2884 {
2885   const int *ptI=_nodal_connec_index->getConstPointer();
2886   const int *pt=_nodal_connec->getConstPointer();
2887   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2888     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2889   else
2890     {
2891       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2892       throw INTERP_KERNEL::Exception(oss.str().c_str());
2893     }
2894 }
2895
2896 /*!
2897  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2898  * This method does not throw exception if geometric type \a type is not in \a this.
2899  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2900  * The coordinates array is not considered here.
2901  *
2902  * \param [in] type the geometric type
2903  * \return cell ids in this having geometric type \a type.
2904  */
2905 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2906 {
2907
2908   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2909   ret->alloc(0,1);
2910   checkConnectivityFullyDefined();
2911   int nbCells=getNumberOfCells();
2912   int mdim=getMeshDimension();
2913   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2914   if(mdim!=(int)cm.getDimension())
2915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2916   const int *ptI=_nodal_connec_index->getConstPointer();
2917   const int *pt=_nodal_connec->getConstPointer();
2918   for(int i=0;i<nbCells;i++)
2919     {
2920       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2921         ret->pushBackSilent(i);
2922     }
2923   return ret.retn();
2924 }
2925
2926 /*!
2927  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2928  */
2929 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2930 {
2931   const int *ptI=_nodal_connec_index->getConstPointer();
2932   const int *pt=_nodal_connec->getConstPointer();
2933   int nbOfCells=getNumberOfCells();
2934   int ret=0;
2935   for(int i=0;i<nbOfCells;i++)
2936     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2937       ret++;
2938   return ret;
2939 }
2940
2941 /*!
2942  * Returns the nodal connectivity of a given cell.
2943  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2944  * all returned node ids can be used in getCoordinatesOfNode().
2945  *  \param [in] cellId - an id of the cell of interest.
2946  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2947  *         cleared before the appending.
2948  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2949  */
2950 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2951 {
2952   const int *ptI=_nodal_connec_index->getConstPointer();
2953   const int *pt=_nodal_connec->getConstPointer();
2954   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2955     if(*w>=0)
2956       conn.push_back(*w);
2957 }
2958
2959 std::string MEDCouplingUMesh::simpleRepr() const
2960 {
2961   static const char msg0[]="No coordinates specified !";
2962   std::ostringstream ret;
2963   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2964   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2965   int tmpp1,tmpp2;
2966   double tt=getTime(tmpp1,tmpp2);
2967   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2968   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2969   if(_mesh_dim>=-1)
2970     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2971   else
2972     { ret << " Mesh dimension has not been set or is invalid !"; }
2973   if(_coords!=0)
2974     {
2975       const int spaceDim=getSpaceDimension();
2976       ret << spaceDim << "\nInfo attached on space dimension : ";
2977       for(int i=0;i<spaceDim;i++)
2978         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2979       ret << "\n";
2980     }
2981   else
2982     ret << msg0 << "\n";
2983   ret << "Number of nodes : ";
2984   if(_coords!=0)
2985     ret << getNumberOfNodes() << "\n";
2986   else
2987     ret << msg0 << "\n";
2988   ret << "Number of cells : ";
2989   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2990     ret << getNumberOfCells() << "\n";
2991   else
2992     ret << "No connectivity specified !" << "\n";
2993   ret << "Cell types present : ";
2994   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2995     {
2996       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2997       ret << cm.getRepr() << " ";
2998     }
2999   ret << "\n";
3000   return ret.str();
3001 }
3002
3003 std::string MEDCouplingUMesh::advancedRepr() const
3004 {
3005   std::ostringstream ret;
3006   ret << simpleRepr();
3007   ret << "\nCoordinates array : \n___________________\n\n";
3008   if(_coords)
3009     _coords->reprWithoutNameStream(ret);
3010   else
3011     ret << "No array set !\n";
3012   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3013   reprConnectivityOfThisLL(ret);
3014   return ret.str();
3015 }
3016
3017 /*!
3018  * This method returns a C++ code that is a dump of \a this.
3019  * This method will throw if this is not fully defined.
3020  */
3021 std::string MEDCouplingUMesh::cppRepr() const
3022 {
3023   static const char coordsName[]="coords";
3024   static const char connName[]="conn";
3025   static const char connIName[]="connI";
3026   checkFullyDefined();
3027   std::ostringstream ret; ret << "// coordinates" << std::endl;
3028   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3029   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3030   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3031   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3032   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3033   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3034   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3035   return ret.str();
3036 }
3037
3038 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3039 {
3040   std::ostringstream ret;
3041   reprConnectivityOfThisLL(ret);
3042   return ret.str();
3043 }
3044
3045 /*!
3046  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3047  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3048  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3049  * some algos).
3050  * 
3051  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3052  * 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
3053  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3054  */
3055 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3056 {
3057   int mdim=getMeshDimension();
3058   if(mdim<0)
3059     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3060   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3061   MCAuto<DataArrayInt> tmp1,tmp2;
3062   bool needToCpyCT=true;
3063   if(!_nodal_connec)
3064     {
3065       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3066       needToCpyCT=false;
3067     }
3068   else
3069     {
3070       tmp1=_nodal_connec;
3071       tmp1->incrRef();
3072     }
3073   if(!_nodal_connec_index)
3074     {
3075       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3076       needToCpyCT=false;
3077     }
3078   else
3079     {
3080       tmp2=_nodal_connec_index;
3081       tmp2->incrRef();
3082     }
3083   ret->setConnectivity(tmp1,tmp2,false);
3084   if(needToCpyCT)
3085     ret->_types=_types;
3086   if(!_coords)
3087     {
3088       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3089       ret->setCoords(coords);
3090     }
3091   else
3092     ret->setCoords(_coords);
3093   return ret.retn();
3094 }
3095
3096 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3097 {
3098   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3099     {
3100       int nbOfCells=getNumberOfCells();
3101       const int *c=_nodal_connec->getConstPointer();
3102       const int *ci=_nodal_connec_index->getConstPointer();
3103       for(int i=0;i<nbOfCells;i++)
3104         {
3105           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3106           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3107           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3108           stream << "\n";
3109         }
3110     }
3111   else
3112     stream << "Connectivity not defined !\n";
3113 }
3114
3115 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3116 {
3117   const int *ptI=_nodal_connec_index->getConstPointer();
3118   const int *pt=_nodal_connec->getConstPointer();
3119   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3120     return ptI[cellId+1]-ptI[cellId]-1;
3121   else
3122     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3123 }
3124
3125 /*!
3126  * Returns types of cells of the specified part of \a this mesh.
3127  * This method avoids computing sub-mesh explicitely to get its types.
3128  *  \param [in] begin - an array of cell ids of interest.
3129  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3130  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3131  *         describing the cell types. 
3132  *  \throw If the coordinates array is not set.
3133  *  \throw If the nodal connectivity of cells is not defined.
3134  *  \sa getAllGeoTypes()
3135  */
3136 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3137 {
3138   checkFullyDefined();
3139   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3140   const int *conn=_nodal_connec->getConstPointer();
3141   const int *connIndex=_nodal_connec_index->getConstPointer();
3142   for(const int *w=begin;w!=end;w++)
3143     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3144   return ret;
3145 }
3146
3147 /*!
3148  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3149  * Optionally updates
3150  * a set of types of cells constituting \a this mesh. 
3151  * This method is for advanced users having prepared their connectivity before. For
3152  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3153  *  \param [in] conn - the nodal connectivity array. 
3154  *  \param [in] connIndex - the nodal connectivity index array.
3155  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3156  *         mesh is updated.
3157  */
3158 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3159 {
3160   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3161   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3162   if(isComputingTypes)
3163     computeTypes();
3164   declareAsNew();
3165 }
3166
3167 /*!
3168  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3169  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3170  */
3171 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3172     _nodal_connec(0),_nodal_connec_index(0),
3173     _types(other._types)
3174 {
3175   if(other._nodal_connec)
3176     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3177   if(other._nodal_connec_index)
3178     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3179 }
3180
3181 MEDCouplingUMesh::~MEDCouplingUMesh()
3182 {
3183   if(_nodal_connec)
3184     _nodal_connec->decrRef();
3185   if(_nodal_connec_index)
3186     _nodal_connec_index->decrRef();
3187 }
3188
3189 /*!
3190  * Recomputes a set of cell types of \a this mesh. For more info see
3191  * \ref MEDCouplingUMeshNodalConnectivity.
3192  */
3193 void MEDCouplingUMesh::computeTypes()
3194 {
3195   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3196 }
3197
3198 /*!
3199  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3200  */
3201 void MEDCouplingUMesh::checkFullyDefined() const
3202 {
3203   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3204     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3205 }
3206
3207 /*!
3208  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3209  */
3210 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3211 {
3212   if(!_nodal_connec_index || !_nodal_connec)
3213     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3214 }
3215
3216 /*!
3217  * Returns a number of cells constituting \a this mesh. 
3218  *  \return int - the number of cells in \a this mesh.
3219  *  \throw If the nodal connectivity of cells is not defined.
3220  */
3221 int MEDCouplingUMesh::getNumberOfCells() const
3222
3223   if(_nodal_connec_index)
3224     return _nodal_connec_index->getNumberOfTuples()-1;
3225   else
3226     if(_mesh_dim==-1)
3227       return 1;
3228     else
3229       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3230 }
3231
3232 /*!
3233  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3234  * mesh. For more info see \ref meshes.
3235  *  \return int - the dimension of \a this mesh.
3236  *  \throw If the mesh dimension is not defined using setMeshDimension().
3237  */
3238 int MEDCouplingUMesh::getMeshDimension() const
3239 {
3240   if(_mesh_dim<-1)
3241     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3242   return _mesh_dim;
3243 }
3244
3245 /*!
3246  * Returns a length of the nodal connectivity array.
3247  * This method is for test reason. Normally the integer returned is not useable by
3248  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3249  *  \return int - the length of the nodal connectivity array.
3250  */
3251 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3252 {
3253   return _nodal_connec->getNbOfElems();
3254 }
3255
3256 /*!
3257  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3258  */
3259 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3260 {
3261   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3262   tinyInfo.push_back(getMeshDimension());
3263   tinyInfo.push_back(getNumberOfCells());
3264   if(_nodal_connec)
3265     tinyInfo.push_back(getNodalConnectivityArrayLen());
3266   else
3267     tinyInfo.push_back(-1);
3268 }
3269
3270 /*!
3271  * First step of unserialization process.
3272  */
3273 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3274 {
3275   return tinyInfo[6]<=0;
3276 }
3277
3278 /*!
3279  * Second step of serialization process.
3280  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3281  * \param a1
3282  * \param a2
3283  * \param littleStrings
3284  */
3285 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3286 {
3287   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3288   if(tinyInfo[5]!=-1)
3289     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3290 }
3291
3292 /*!
3293  * Third and final step of serialization process.
3294  */
3295 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3296 {
3297   MEDCouplingPointSet::serialize(a1,a2);
3298   if(getMeshDimension()>-1)
3299     {
3300       a1=DataArrayInt::New();
3301       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3302       int *ptA1=a1->getPointer();
3303       const int *conn=getNodalConnectivity()->getConstPointer();
3304       const int *index=getNodalConnectivityIndex()->getConstPointer();
3305       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3306       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3307     }
3308   else
3309     a1=0;
3310 }
3311
3312 /*!
3313  * Second and final unserialization process.
3314  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3315  */
3316 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3317 {
3318   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3319   setMeshDimension(tinyInfo[5]);
3320   if(tinyInfo[7]!=-1)
3321     {
3322       // Connectivity
3323       const int *recvBuffer=a1->getConstPointer();
3324       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3325       myConnecIndex->alloc(tinyInfo[6]+1,1);
3326       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3327       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3328       myConnec->alloc(tinyInfo[7],1);
3329       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3330       setConnectivity(myConnec, myConnecIndex);
3331     }
3332 }
3333
3334 /*!
3335  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3336  * CellIds are given using range specified by a start an end and step.
3337  */
3338 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3339 {
3340   checkFullyDefined();
3341   int ncell=getNumberOfCells();
3342   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3343   ret->_mesh_dim=_mesh_dim;
3344   ret->setCoords(_coords);
3345   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3346   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3347   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3348   int work=start;
3349   const int *conn=_nodal_connec->getConstPointer();
3350   const int *connIndex=_nodal_connec_index->getConstPointer();
3351   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3352     {
3353       if(work>=0 && work<ncell)
3354         {
3355           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3356         }
3357       else
3358         {
3359           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3360           throw INTERP_KERNEL::Exception(oss.str().c_str());
3361         }
3362     }
3363   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3364   int *newConnPtr=newConn->getPointer();
3365   std::set<INTERP_KERNEL::NormalizedCellType> types;
3366   work=start;
3367   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3368     {
3369       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3370       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3371     }
3372   ret->setConnectivity(newConn,newConnI,false);
3373   ret->_types=types;
3374   ret->copyTinyInfoFrom(this);
3375   return ret.retn();
3376 }
3377
3378 /*!
3379  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3380  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3381  * The return newly allocated mesh will share the same coordinates as \a this.
3382  */
3383 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3384 {
3385   checkConnectivityFullyDefined();
3386   int ncell=getNumberOfCells();
3387   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3388   ret->_mesh_dim=_mesh_dim;
3389   ret->setCoords(_coords);
3390   std::size_t nbOfElemsRet=std::distance(begin,end);
3391   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3392   connIndexRet[0]=0;
3393   const int *conn=_nodal_connec->getConstPointer();
3394   const int *connIndex=_nodal_connec_index->getConstPointer();
3395   int newNbring=0;
3396   for(const int *work=begin;work!=end;work++,newNbring++)
3397     {
3398       if(*work>=0 && *work<ncell)
3399         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3400       else
3401         {
3402           free(connIndexRet);
3403           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3404           throw INTERP_KERNEL::Exception(oss.str().c_str());
3405         }
3406     }
3407   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3408   int *connRetWork=connRet;
3409   std::set<INTERP_KERNEL::NormalizedCellType> types;
3410   for(const int *work=begin;work!=end;work++)
3411     {
3412       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3413       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3414     }
3415   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3416   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3417   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3418   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3419   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3420   ret->_types=types;
3421   ret->copyTinyInfoFrom(this);
3422   return ret.retn();
3423 }
3424
3425 /*!
3426  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3427  * mesh.<br>
3428  * For 1D cells, the returned field contains lengths.<br>
3429  * For 2D cells, the returned field contains areas.<br>
3430  * For 3D cells, the returned field contains volumes.
3431  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3432  *         orientation, i.e. the volume is always positive.
3433  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3434  *         and one time . The caller is to delete this field using decrRef() as it is no
3435  *         more needed.
3436  */
3437 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3438 {
3439   std::string name="MeasureOfMesh_";
3440   name+=getName();
3441   int nbelem=getNumberOfCells();
3442   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3443   field->setName(name);
3444   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3445   array->alloc(nbelem,1);
3446   double *area_vol=array->getPointer();
3447   field->setArray(array) ; array=0;
3448   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3449   field->synchronizeTimeWithMesh();
3450   if(getMeshDimension()!=-1)
3451     {
3452       int ipt;
3453       INTERP_KERNEL::NormalizedCellType type;
3454       int dim_space=getSpaceDimension();
3455       const double *coords=getCoords()->getConstPointer();
3456       const int *connec=getNodalConnectivity()->getConstPointer();
3457       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3458       for(int iel=0;iel<nbelem;iel++)
3459         {
3460           ipt=connec_index[iel];
3461           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3462           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);
3463         }
3464       if(isAbs)
3465         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3466     }
3467   else
3468     {
3469       area_vol[0]=std::numeric_limits<double>::max();
3470     }
3471   return field.retn();
3472 }
3473
3474 /*!
3475  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3476  * mesh.<br>
3477  * For 1D cells, the returned array contains lengths.<br>
3478  * For 2D cells, the returned array contains areas.<br>
3479  * For 3D cells, the returned array contains volumes.
3480  * This method avoids building explicitly a part of \a this mesh to perform the work.
3481  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3482  *         orientation, i.e. the volume is always positive.
3483  *  \param [in] begin - an array of cell ids of interest.
3484  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3485  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3486  *          delete this array using decrRef() as it is no more needed.
3487  * 
3488  *  \if ENABLE_EXAMPLES
3489  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3490  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3491  *  \endif
3492  *  \sa getMeasureField()
3493  */
3494 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3495 {
3496   std::string name="PartMeasureOfMesh_";
3497   name+=getName();
3498   int nbelem=(int)std::distance(begin,end);
3499   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3500   array->setName(name);
3501   array->alloc(nbelem,1);
3502   double *area_vol=array->getPointer();
3503   if(getMeshDimension()!=-1)
3504     {
3505       int ipt;
3506       INTERP_KERNEL::NormalizedCellType type;
3507       int dim_space=getSpaceDimension();
3508       const double *coords=getCoords()->getConstPointer();
3509       const int *connec=getNodalConnectivity()->getConstPointer();
3510       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3511       for(const int *iel=begin;iel!=end;iel++)
3512         {
3513           ipt=connec_index[*iel];
3514           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3515           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3516         }
3517       if(isAbs)
3518         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3519     }
3520   else
3521     {
3522       area_vol[0]=std::numeric_limits<double>::max();
3523     }
3524   return array.retn();
3525 }
3526
3527 /*!
3528  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3529  * \a this one. The returned field contains the dual cell volume for each corresponding
3530  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3531  *  the dual mesh in P1 sens of \a this.<br>
3532  * For 1D cells, the returned field contains lengths.<br>
3533  * For 2D cells, the returned field contains areas.<br>
3534  * For 3D cells, the returned field contains volumes.
3535  * This method is useful to check "P1*" conservative interpolators.
3536  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3537  *         orientation, i.e. the volume is always positive.
3538  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3539  *          nodes and one time. The caller is to delete this array using decrRef() as
3540  *          it is no more needed.
3541  */
3542 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3543 {
3544   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3545   std::string name="MeasureOnNodeOfMesh_";
3546   name+=getName();
3547   int nbNodes=getNumberOfNodes();
3548   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3549   double cst=1./((double)getMeshDimension()+1.);
3550   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3551   array->alloc(nbNodes,1);
3552   double *valsToFill=array->getPointer();
3553   std::fill(valsToFill,valsToFill+nbNodes,0.);
3554   const double *values=tmp->getArray()->getConstPointer();
3555   MCAuto<DataArrayInt> da=DataArrayInt::New();
3556   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3557   getReverseNodalConnectivity(da,daInd);
3558   const int *daPtr=da->getConstPointer();
3559   const int *daIPtr=daInd->getConstPointer();
3560   for(int i=0;i<nbNodes;i++)
3561     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3562       valsToFill[i]+=cst*values[*cell];
3563   ret->setMesh(this);
3564   ret->setArray(array);
3565   return ret.retn();
3566 }
3567
3568 /*!
3569  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3570  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3571  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3572  * and are normalized.
3573  * <br> \a this can be either 
3574  * - a  2D mesh in 2D or 3D space or 
3575  * - an 1D mesh in 2D space.
3576  * 
3577  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3578  *          cells and one time. The caller is to delete this field using decrRef() as
3579  *          it is no more needed.
3580  *  \throw If the nodal connectivity of cells is not defined.
3581  *  \throw If the coordinates array is not set.
3582  *  \throw If the mesh dimension is not set.
3583  *  \throw If the mesh and space dimension is not as specified above.
3584  */
3585 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3586 {
3587   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3588     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3589   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3590   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3591   int nbOfCells=getNumberOfCells();
3592   int nbComp=getMeshDimension()+1;
3593   array->alloc(nbOfCells,nbComp);
3594   double *vals=array->getPointer();
3595   const int *connI=_nodal_connec_index->getConstPointer();
3596   const int *conn=_nodal_connec->getConstPointer();
3597   const double *coords=_coords->getConstPointer();
3598   if(getMeshDimension()==2)
3599     {
3600       if(getSpaceDimension()==3)
3601         {
3602           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3603           const double *locPtr=loc->getConstPointer();
3604           for(int i=0;i<nbOfCells;i++,vals+=3)
3605             {
3606               int offset=connI[i];
3607               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3608               double n=INTERP_KERNEL::norm<3>(vals);
3609               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3610             }
3611         }
3612       else
3613         {
3614           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3615           const double *isAbsPtr=isAbs->getArray()->begin();
3616           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3617             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3618         }
3619     }
3620   else//meshdimension==1
3621     {
3622       double tmp[2];
3623       for(int i=0;i<nbOfCells;i++)
3624         {
3625           int offset=connI[i];
3626           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3627           double n=INTERP_KERNEL::norm<2>(tmp);
3628           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3629           *vals++=-tmp[1];
3630           *vals++=tmp[0];
3631         }
3632     }
3633   ret->setArray(array);
3634   ret->setMesh(this);
3635   ret->synchronizeTimeWithSupport();
3636   return ret.retn();
3637 }
3638
3639 /*!
3640  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3641  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3642  * and are normalized.
3643  * <br> \a this can be either 
3644  * - a  2D mesh in 2D or 3D space or 
3645  * - an 1D mesh in 2D space.
3646  * 
3647  * This method avoids building explicitly a part of \a this mesh to perform the work.
3648  *  \param [in] begin - an array of cell ids of interest.
3649  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3650  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3651  *          cells and one time. The caller is to delete this field using decrRef() as
3652  *          it is no more needed.
3653  *  \throw If the nodal connectivity of cells is not defined.
3654  *  \throw If the coordinates array is not set.
3655  *  \throw If the mesh dimension is not set.
3656  *  \throw If the mesh and space dimension is not as specified above.
3657  *  \sa buildOrthogonalField()
3658  *
3659  *  \if ENABLE_EXAMPLES
3660  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3661  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3662  *  \endif
3663  */
3664 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3665 {
3666   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3667     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3668   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3669   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3670   std::size_t nbelems=std::distance(begin,end);
3671   int nbComp=getMeshDimension()+1;
3672   array->alloc((int)nbelems,nbComp);
3673   double *vals=array->getPointer();
3674   const int *connI=_nodal_connec_index->getConstPointer();
3675   const int *conn=_nodal_connec->getConstPointer();
3676   const double *coords=_coords->getConstPointer();
3677   if(getMeshDimension()==2)
3678     {
3679       if(getSpaceDimension()==3)
3680         {
3681           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3682           const double *locPtr=loc->getConstPointer();
3683           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3684             {
3685               int offset=connI[*i];
3686               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3687               double n=INTERP_KERNEL::norm<3>(vals);
3688               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3689             }
3690         }
3691       else
3692         {
3693           for(std::size_t i=0;i<nbelems;i++)
3694             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3695         }
3696     }
3697   else//meshdimension==1
3698     {
3699       double tmp[2];
3700       for(const int *i=begin;i!=end;i++)
3701         {
3702           int offset=connI[*i];
3703           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3704           double n=INTERP_KERNEL::norm<2>(tmp);
3705           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3706           *vals++=-tmp[1];
3707           *vals++=tmp[0];
3708         }
3709     }
3710   ret->setArray(array);
3711   ret->setMesh(this);
3712   ret->synchronizeTimeWithSupport();
3713   return ret.retn();
3714 }
3715
3716 /*!
3717  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3718  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3719  * and are \b not normalized.
3720  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3721  *          cells and one time. The caller is to delete this field using decrRef() as
3722  *          it is no more needed.
3723  *  \throw If the nodal connectivity of cells is not defined.
3724  *  \throw If the coordinates array is not set.
3725  *  \throw If \a this->getMeshDimension() != 1.
3726  *  \throw If \a this mesh includes cells of type other than SEG2.
3727  */
3728 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3729 {
3730   if(getMeshDimension()!=1)
3731     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3732   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3733     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3734   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3735   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3736   int nbOfCells=getNumberOfCells();
3737   int spaceDim=getSpaceDimension();
3738   array->alloc(nbOfCells,spaceDim);
3739   double *pt=array->getPointer();
3740   const double *coo=getCoords()->getConstPointer();
3741   std::vector<int> conn;
3742   conn.reserve(2);
3743   for(int i=0;i<nbOfCells;i++)
3744     {
3745       conn.resize(0);
3746       getNodeIdsOfCell(i,conn);
3747       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3748     }
3749   ret->setArray(array);
3750   ret->setMesh(this);
3751   ret->synchronizeTimeWithSupport();
3752   return ret.retn();
3753 }
3754
3755 /*!
3756  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3757  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3758  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3759  * from. If a result face is shared by two 3D cells, then the face in included twice in
3760  * the result mesh.
3761  *  \param [in] origin - 3 components of a point defining location of the plane.
3762  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3763  *         must be greater than 1e-6.
3764  *  \param [in] eps - half-thickness of the plane.
3765  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3766  *         producing correspondent 2D cells. The caller is to delete this array
3767  *         using decrRef() as it is no more needed.
3768  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3769  *         not share the node coordinates array with \a this mesh. The caller is to
3770  *         delete this mesh using decrRef() as it is no more needed.  
3771  *  \throw If the coordinates array is not set.
3772  *  \throw If the nodal connectivity of cells is not defined.
3773  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3774  *  \throw If magnitude of \a vec is less than 1e-6.
3775  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3776  *  \throw If \a this includes quadratic cells.
3777  */
3778 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3779 {
3780   checkFullyDefined();
3781   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3783   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3784   if(candidates->empty())
3785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3786   std::vector<int> nodes;
3787   DataArrayInt *cellIds1D=0;
3788   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3789   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3790   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3791   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3792   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3793   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3794   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3795   revDesc2=0; revDescIndx2=0;
3796   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3797   revDesc1=0; revDescIndx1=0;
3798   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3799   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3800   //
3801   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3802   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3803     cut3DCurve[*it]=-1;
3804   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3805   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3806   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3807                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3808                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3809   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3810   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3811   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3812   if(cellIds2->empty())
3813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3814   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3815   ret->setCoords(mDesc1->getCoords());
3816   ret->setConnectivity(conn,connI,true);
3817   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3818   return ret.retn();
3819 }
3820
3821 /*!
3822  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3823 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
3824 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3825 the result mesh.
3826  *  \param [in] origin - 3 components of a point defining location of the plane.
3827  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3828  *         must be greater than 1e-6.
3829  *  \param [in] eps - half-thickness of the plane.
3830  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3831  *         producing correspondent segments. The caller is to delete this array
3832  *         using decrRef() as it is no more needed.
3833  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3834  *         mesh in 3D space. This mesh does not share the node coordinates array with
3835  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3836  *         no more needed. 
3837  *  \throw If the coordinates array is not set.
3838  *  \throw If the nodal connectivity of cells is not defined.
3839  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3840  *  \throw If magnitude of \a vec is less than 1e-6.
3841  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3842  *  \throw If \a this includes quadratic cells.
3843  */
3844 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3845 {
3846   checkFullyDefined();
3847   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3849   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3850   if(candidates->empty())
3851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3852   std::vector<int> nodes;
3853   DataArrayInt *cellIds1D=0;
3854   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3855   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3856   MCAuto<DataArrayInt> desc1=DataArrayInt::New();
3857   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New();
3858   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New();
3859   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New();
3860   MCAuto<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3861   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3862   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3863   //
3864   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3865   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3866     cut3DCurve[*it]=-1;
3867   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3868   int ncellsSub=subMesh->getNumberOfCells();
3869   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3870   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3871                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3872                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3873   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3874   conn->alloc(0,1);
3875   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3876   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3877   for(int i=0;i<ncellsSub;i++)
3878     {
3879       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3880         {
3881           if(cut3DSurf[i].first!=-2)
3882             {
3883               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3884               connI->pushBackSilent(conn->getNumberOfTuples());
3885               cellIds2->pushBackSilent(i);
3886             }
3887           else
3888             {
3889               int cellId3DSurf=cut3DSurf[i].second;
3890               int offset=nodalI[cellId3DSurf]+1;
3891               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3892               for(int j=0;j<nbOfEdges;j++)
3893                 {
3894                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3895                   connI->pushBackSilent(conn->getNumberOfTuples());
3896                   cellIds2->pushBackSilent(cellId3DSurf);
3897                 }
3898             }
3899         }
3900     }
3901   if(cellIds2->empty())
3902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3903   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3904   ret->setCoords(mDesc1->getCoords());
3905   ret->setConnectivity(conn,connI,true);
3906   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3907   return ret.retn();
3908 }
3909
3910 /*!
3911  * Finds cells whose bounding boxes intersect a given plane.
3912  *  \param [in] origin - 3 components of a point defining location of the plane.
3913  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3914  *         must be greater than 1e-6.
3915  *  \param [in] eps - half-thickness of the plane.
3916  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3917  *         cells. The caller is to delete this array using decrRef() as it is no more
3918  *         needed.
3919  *  \throw If the coordinates array is not set.
3920  *  \throw If the nodal connectivity of cells is not defined.
3921  *  \throw If \a this->getSpaceDimension() != 3.
3922  *  \throw If magnitude of \a vec is less than 1e-6.
3923  *  \sa buildSlice3D()
3924  */
3925 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3926 {
3927   checkFullyDefined();
3928   if(getSpaceDimension()!=3)
3929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3930   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3931   if(normm<1e-6)
3932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3933   double vec2[3];
3934   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3935   double angle=acos(vec[2]/normm);
3936   MCAuto<DataArrayInt> cellIds;
3937   double bbox[6];
3938   if(angle>eps)
3939     {
3940       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3941       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3942       if(normm2/normm>1e-6)
3943         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3944       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3945       mw->setCoords(coo);
3946       mw->getBoundingBox(bbox);
3947       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3948       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3949     }
3950   else
3951     {
3952       getBoundingBox(bbox);
3953       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3954       cellIds=getCellsInBoundingBox(bbox,eps);
3955     }
3956   return cellIds.retn();
3957 }
3958
3959 /*!
3960  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3961  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3962  * No consideration of coordinate is done by this method.
3963  * 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)
3964  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3965  */
3966 bool MEDCouplingUMesh::isContiguous1D() const
3967 {
3968   if(getMeshDimension()!=1)
3969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3970   int nbCells=getNumberOfCells();
3971   if(nbCells<1)
3972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3973   const int *connI=_nodal_connec_index->getConstPointer();
3974   const int *conn=_nodal_connec->getConstPointer();
3975   int ref=conn[connI[0]+2];
3976   for(int i=1;i<nbCells;i++)
3977     {
3978       if(conn[connI[i]+1]!=ref)
3979         return false;
3980       ref=conn[connI[i]+2];
3981     }
3982   return true;
3983 }
3984
3985 /*!
3986  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3987  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3988  * \param pt reference point of the line
3989  * \param v normalized director vector of the line
3990  * \param eps max precision before throwing an exception
3991  * \param res output of size this->getNumberOfCells
3992  */
3993 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3994 {
3995   if(getMeshDimension()!=1)
3996     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3997   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3998     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3999   if(getSpaceDimension()!=3)
4000     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4001   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4002   const double *fPtr=f->getArray()->getConstPointer();
4003   double tmp[3];
4004   for(int i=0;i<getNumberOfCells();i++)
4005     {
4006       const double *tmp1=fPtr+3*i;
4007       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4008       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4009       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4010       double n1=INTERP_KERNEL::norm<3>(tmp);
4011       n1/=INTERP_KERNEL::norm<3>(tmp1);
4012       if(n1>eps)
4013         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4014     }
4015   const double *coo=getCoords()->getConstPointer();
4016   for(int i=0;i<getNumberOfNodes();i++)
4017     {
4018       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4019       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4020       res[i]=std::accumulate(tmp,tmp+3,0.);
4021     }
4022 }
4023
4024 /*!
4025  * 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. 
4026  * \a this is expected to be a mesh so that its space dimension is equal to its
4027  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4028  * 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).
4029  *
4030  * 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
4031  * 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).
4032  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4033  *
4034  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4035  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036  *
4037  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4038  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4039  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4040  * \return the positive value of the distance.
4041  * \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
4042  * dimension - 1.
4043  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4044  */
4045 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4046 {
4047   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4048   if(meshDim!=spaceDim-1)
4049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4050   if(meshDim!=2 && meshDim!=1)
4051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4052   checkFullyDefined();
4053   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4054     { 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()); }
4055   DataArrayInt *ret1=0;
4056   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4057   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4058   MCAuto<DataArrayInt> ret1Safe(ret1);
4059   cellId=*ret1Safe->begin();
4060   return *ret0->begin();
4061 }
4062
4063 /*!
4064  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4065  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4066  * 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
4067  * 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).
4068  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4069  * 
4070  * \a this is expected to be a mesh so that its space dimension is equal to its
4071  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4072  * 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).
4073  *
4074  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4075  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4076  *
4077  * \param [in] pts the list of points in which each tuple represents a point
4078  * \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.
4079  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4080  * \throw if number of components of \a pts is not equal to the space dimension.
4081  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4082  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4083  */
4084 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4085 {
4086   if(!pts)
4087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4088   pts->checkAllocated();
4089   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4090   if(meshDim!=spaceDim-1)
4091     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4092   if(meshDim!=2 && meshDim!=1)
4093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4094   if(pts->getNumberOfComponents()!=spaceDim)
4095     {
4096       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4097       throw INTERP_KERNEL::Exception(oss.str().c_str());
4098     }
4099   checkFullyDefined();
4100   int nbCells=getNumberOfCells();
4101   if(nbCells==0)
4102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4103   int nbOfPts=pts->getNumberOfTuples();
4104   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4105   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4106   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4107   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4108   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4109   const double *bbox(bboxArr->begin());
4110   switch(spaceDim)
4111   {
4112     case 3:
4113       {
4114         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4115         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4116           {
4117             double x=std::numeric_limits<double>::max();
4118             std::vector<int> elems;
4119             myTree.getMinDistanceOfMax(ptsPtr,x);
4120             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4121             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4122           }
4123         break;
4124       }
4125     case 2:
4126       {
4127         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4128         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4129           {
4130             double x=std::numeric_limits<double>::max();
4131             std::vector<int> elems;
4132             myTree.getMinDistanceOfMax(ptsPtr,x);
4133             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4134             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4135           }
4136         break;
4137       }
4138     default:
4139       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4140   }
4141   cellIds=ret1.retn();
4142   return ret0.retn();
4143 }
4144
4145 /// @cond INTERNAL
4146
4147 /*!
4148  * \param [in] pt the start pointer (included) of the coordinates of the point
4149  * \param [in] cellIdsBg the start pointer (included) of cellIds
4150  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4151  * \param [in] nc nodal connectivity
4152  * \param [in] ncI nodal connectivity index
4153  * \param [in,out] ret0 the min distance between \a this and the external input point
4154  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4155  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4156  */
4157 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)
4158 {
4159   cellId=-1;
4160   ret0=std::numeric_limits<double>::max();
4161   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4162     {
4163       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4164       {
4165         case INTERP_KERNEL::NORM_TRI3:
4166           {
4167             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4168             if(tmp<ret0)
4169               { ret0=tmp; cellId=*zeCell; }
4170             break;
4171           }
4172         case INTERP_KERNEL::NORM_QUAD4:
4173         case INTERP_KERNEL::NORM_POLYGON:
4174           {
4175             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4176             if(tmp<ret0)
4177               { ret0=tmp; cellId=*zeCell; }
4178             break;
4179           }
4180         default:
4181           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4182       }
4183     }
4184 }
4185
4186 /*!
4187  * \param [in] pt the start pointer (included) of the coordinates of the point
4188  * \param [in] cellIdsBg the start pointer (included) of cellIds
4189  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4190  * \param [in] nc nodal connectivity
4191  * \param [in] ncI nodal connectivity index
4192  * \param [in,out] ret0 the min distance between \a this and the external input point
4193  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4194  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4195  */
4196 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)
4197 {
4198   cellId=-1;
4199   ret0=std::numeric_limits<double>::max();
4200   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4201     {
4202       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4203       {
4204         case INTERP_KERNEL::NORM_SEG2:
4205           {
4206             std::size_t uselessEntry=0;
4207             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4208             tmp=sqrt(tmp);
4209             if(tmp<ret0)
4210               { ret0=tmp; cellId=*zeCell; }
4211             break;
4212           }
4213         default:
4214           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4215       }
4216     }
4217 }
4218 /// @endcond
4219
4220 /*!
4221  * Finds cells in contact with a ball (i.e. a point with precision). 
4222  * 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.
4223  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4224  *
4225  * \warning This method is suitable if the caller intends to evaluate only one
4226  *          point, for more points getCellsContainingPoints() is recommended as it is
4227  *          faster. 
4228  *  \param [in] pos - array of coordinates of the ball central point.
4229  *  \param [in] eps - ball radius.
4230  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4231  *         if there are no such cells.
4232  *  \throw If the coordinates array is not set.
4233  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4234  */
4235 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4236 {
4237   std::vector<int> elts;
4238   getCellsContainingPoint(pos,eps,elts);
4239   if(elts.empty())
4240     return -1;
4241   return elts.front();
4242 }
4243
4244 /*!
4245  * Finds cells in contact with a ball (i.e. a point with precision).
4246  * 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.
4247  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4248  * \warning This method is suitable if the caller intends to evaluate only one
4249  *          point, for more points getCellsContainingPoints() is recommended as it is
4250  *          faster. 
4251  *  \param [in] pos - array of coordinates of the ball central point.
4252  *  \param [in] eps - ball radius.
4253  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4254  *         before inserting ids.
4255  *  \throw If the coordinates array is not set.
4256  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4257  *
4258  *  \if ENABLE_EXAMPLES
4259  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4260  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4261  *  \endif
4262  */
4263 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4264 {
4265   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4266   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4267   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4268 }
4269
4270 /// @cond INTERNAL
4271
4272 namespace MEDCoupling
4273 {
4274   template<const int SPACEDIMM>
4275   class DummyClsMCUG
4276   {
4277   public:
4278     static const int MY_SPACEDIM=SPACEDIMM;
4279     static const int MY_MESHDIM=8;
4280     typedef int MyConnType;
4281     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4282     // begin
4283     // useless, but for windows compilation ...
4284     const double* getCoordinatesPtr() const { return 0; }
4285     const int* getConnectivityPtr() const { return 0; }
4286     const int* getConnectivityIndexPtr() const { return 0; }
4287     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4288     // end
4289   };
4290
4291   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4292   {
4293     INTERP_KERNEL::Edge *ret(0);
4294     MCAuto<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]));
4295     m[n0]=bg[0]; m[n1]=bg[1];
4296     switch(typ)
4297     {
4298       case INTERP_KERNEL::NORM_SEG2:
4299         {
4300           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4301           break;
4302         }
4303       case INTERP_KERNEL::NORM_SEG3:
4304         {
4305           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4306           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4307           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4308           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4309           bool colinearity(inters.areColinears());
4310           delete e1; delete e2;
4311           if(colinearity)
4312             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4313           else
4314             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4315           break;
4316         }
4317       default:
4318         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4319     }
4320     return ret;
4321   }
4322
4323   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4324   {
4325     INTERP_KERNEL::Edge *ret=0;
4326     switch(typ)
4327     {
4328       case INTERP_KERNEL::NORM_SEG2:
4329         {
4330           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4331           break;
4332         }
4333       case INTERP_KERNEL::NORM_SEG3:
4334         {
4335           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4336           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4337           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4338           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4339           bool colinearity=inters.areColinears();
4340           delete e1; delete e2;
4341           if(colinearity)
4342             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4343           else
4344             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4345           mapp2[bg[2]].second=false;
4346           break;
4347         }
4348       default:
4349         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4350     }
4351     return ret;
4352   }
4353
4354   /*!
4355    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4356    * the global mesh 'mDesc'.
4357    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4358    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4359    */
4360   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4361                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4362   {
4363     mapp.clear();
4364     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.
4365     const double *coo=mDesc->getCoords()->getConstPointer();
4366     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4367     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4368     std::set<int> s;
4369     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4370       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4371     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4372       {
4373         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4374         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4375       }
4376     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4377     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4378       {
4379         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4380         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4381       }
4382     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4383       {
4384         if((*it2).second.second)
4385           mapp[(*it2).second.first]=(*it2).first;
4386         ((*it2).second.first)->decrRef();
4387       }
4388     return ret;
4389   }
4390
4391   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4392   {
4393     if(nodeId>=offset2)
4394       {
4395         int locId=nodeId-offset2;
4396         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4397       }
4398     if(nodeId>=offset1)
4399       {
4400         int locId=nodeId-offset1;
4401         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4402       }
4403     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4404   }
4405
4406   /**
4407    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4408    */
4409   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4410                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4411                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4412   {
4413     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4414       {
4415         int eltId1=abs(*desc1)-1;
4416         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4417           {
4418             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4419             if(it==mappRev.end())
4420               {
4421                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4422                 mapp[node]=*it1;
4423                 mappRev[*it1]=node;
4424               }
4425           }
4426       }
4427   }
4428 }
4429
4430 /// @endcond
4431
4432 template<int SPACEDIM>
4433 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4434                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4435 {
4436   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4437   int *eltsIndexPtr(eltsIndex->getPointer());
4438   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4439   const double *bbox(bboxArr->begin());
4440   int nbOfCells=getNumberOfCells();
4441   const int *conn=_nodal_connec->getConstPointer();
4442   const int *connI=_nodal_connec_index->getConstPointer();
4443   double bb[2*SPACEDIM];
4444   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4445   for(int i=0;i<nbOfPoints;i++)
4446     {
4447       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4448       for(int j=0;j<SPACEDIM;j++)
4449         {
4450           bb[2*j]=pos[SPACEDIM*i+j];
4451           bb[2*j+1]=pos[SPACEDIM*i+j];
4452         }
4453       std::vector<int> candidates;
4454       myTree.getIntersectingElems(bb,candidates);
4455       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4456         {
4457           int sz(connI[(*iter)+1]-connI[*iter]-1);
4458           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4459           bool status(false);
4460           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4461             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4462           else
4463             {
4464               if(SPACEDIM!=2)
4465                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4466               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4467               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4468               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4469               INTERP_KERNEL::QuadraticPolygon *pol(0);
4470               for(int j=0;j<sz;j++)
4471                 {
4472                   int nodeId(conn[connI[*iter]+1+j]);
4473                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4474                 }
4475               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4476                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4477               else
4478                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4479               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4480               double a(0.),b(0.),c(0.);
4481               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4482               status=pol->isInOrOut2(n);
4483               delete pol; n->decrRef();
4484             }
4485           if(status)
4486             {
4487               eltsIndexPtr[i+1]++;
4488               elts->pushBackSilent(*iter);
4489             }
4490         }
4491     }
4492 }
4493 /*!
4494  * Finds cells in contact with several balls (i.e. points with precision).
4495  * This method is an extension of getCellContainingPoint() and
4496  * getCellsContainingPoint() for the case of multiple points.
4497  * 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.
4498  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4499  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4500  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4501  *         this->getSpaceDimension() * \a nbOfPoints 
4502  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4503  *  \param [in] eps - radius of balls (i.e. the precision).
4504  *  \param [out] elts - vector returning ids of found cells.
4505  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4506  *         dividing cell ids in \a elts into groups each referring to one
4507  *         point. Its every element (except the last one) is an index pointing to the
4508  *         first id of a group of cells. For example cells in contact with the *i*-th
4509  *         point are described by following range of indices:
4510  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4511  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4512  *         Number of cells in contact with the *i*-th point is
4513  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4514  *  \throw If the coordinates array is not set.
4515  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4516  *
4517  *  \if ENABLE_EXAMPLES
4518  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4519  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4520  *  \endif
4521  */
4522 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4523                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4524 {
4525   int spaceDim=getSpaceDimension();
4526   int mDim=getMeshDimension();
4527   if(spaceDim==3)
4528     {
4529       if(mDim==3)
4530         {
4531           const double *coords=_coords->getConstPointer();
4532           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4533         }
4534       /*else if(mDim==2)
4535         {
4536
4537         }*/
4538       else
4539         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4540     }
4541   else if(spaceDim==2)
4542     {
4543       if(mDim==2)
4544         {
4545           const double *coords=_coords->getConstPointer();
4546           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4547         }
4548       else
4549         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4550     }
4551   else if(spaceDim==1)
4552     {
4553       if(mDim==1)
4554         {
4555           const double *coords=_coords->getConstPointer();
4556           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4557         }
4558       else
4559         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4560     }
4561   else
4562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4563 }
4564
4565 /*!
4566  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4567  * least two its edges intersect each other anywhere except their extremities. An
4568  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4569  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4570  *         cleared before filling in.
4571  *  \param [in] eps - precision.
4572  *  \throw If \a this->getMeshDimension() != 2.
4573  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4574  */
4575 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4576 {
4577   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4578   if(getMeshDimension()!=2)
4579     throw INTERP_KERNEL::Exception(msg);
4580   int spaceDim=getSpaceDimension();
4581   if(spaceDim!=2 && spaceDim!=3)
4582     throw INTERP_KERNEL::Exception(msg);
4583   const int *conn=_nodal_connec->getConstPointer();
4584   const int *connI=_nodal_connec_index->getConstPointer();
4585   int nbOfCells=getNumberOfCells();
4586   std::vector<double> cell2DinS2;
4587   for(int i=0;i<nbOfCells;i++)
4588     {
4589       int offset=connI[i];
4590       int nbOfNodesForCell=connI[i+1]-offset-1;
4591       if(nbOfNodesForCell<=3)
4592         continue;
4593       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4594       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4595       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4596         cells.push_back(i);
4597       cell2DinS2.clear();
4598     }
4599 }
4600
4601 /*!
4602  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4603  *
4604  * 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.
4605  * 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.
4606  * 
4607  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4608  * This convex envelop is computed using Jarvis march algorithm.
4609  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4610  * 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)
4611  * 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.
4612  *
4613  * \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.
4614  * \sa MEDCouplingUMesh::colinearize2D
4615  */
4616 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4617 {
4618   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4620   checkFullyDefined();
4621   const double *coords=getCoords()->getConstPointer();
4622   int nbOfCells=getNumberOfCells();
4623   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4624   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4625   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4626   int *workIndexOut=nodalConnecIndexOut->getPointer();
4627   *workIndexOut=0;
4628   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4629   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4630   std::set<INTERP_KERNEL::NormalizedCellType> types;
4631   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4632   isChanged->alloc(0,1);
4633   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4634     {
4635       int pos=nodalConnecOut->getNumberOfTuples();
4636       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4637         isChanged->pushBackSilent(i);
4638       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4639       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4640     }
4641   if(isChanged->empty())
4642     return 0;
4643   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4644   _types=types;
4645   return isChanged.retn();
4646 }
4647
4648 /*!
4649  * This method is \b NOT const because it can modify \a this.
4650  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4651  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4652  * \param policy specifies the type of extrusion chosen:
4653  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4654  *   will be repeated to build each level
4655  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4656  *   the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4657  *   along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4658  *   arc.
4659  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4660  */
4661 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4662 {
4663   checkFullyDefined();
4664   mesh1D->checkFullyDefined();
4665   if(!mesh1D->isContiguous1D())
4666     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4667   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4668     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4669   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4670     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4671   if(mesh1D->getMeshDimension()!=1)
4672     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4673   bool isQuad=false;
4674   if(isPresenceOfQuadratic())
4675     {
4676       if(mesh1D->isFullyQuadratic())
4677         isQuad=true;
4678       else
4679         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4680     }
4681   int oldNbOfNodes(getNumberOfNodes());
4682   MCAuto<DataArrayDouble> newCoords;
4683   switch(policy)
4684   {
4685     case 0:
4686       {
4687         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4688         break;
4689       }
4690     case 1:
4691       {
4692         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4693         break;
4694       }
4695     default:
4696       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4697   }
4698   setCoords(newCoords);
4699   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4700   updateTime();
4701   return ret.retn();
4702 }
4703
4704 /*!
4705  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4706  * If it is not the case an exception will be thrown.
4707  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4708  * intersection of plane defined by ('origin','vec').
4709  * This method has one in/out parameter : 'cut3DCurve'.
4710  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4711  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4712  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4713  * This method will throw an exception if \a this contains a non linear segment.
4714  */
4715 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4716 {
4717   checkFullyDefined();
4718   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4720   int ncells=getNumberOfCells();
4721   int nnodes=getNumberOfNodes();
4722   double vec2[3],vec3[3],vec4[3];
4723   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4724   if(normm<1e-6)
4725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4726   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4727   const int *conn=_nodal_connec->getConstPointer();
4728   const int *connI=_nodal_connec_index->getConstPointer();
4729   const double *coo=_coords->getConstPointer();
4730   std::vector<double> addCoo;
4731   for(int i=0;i<ncells;i++)
4732     {
4733       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4734         {
4735           if(cut3DCurve[i]==-2)
4736             {
4737               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4738               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];
4739               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4740               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4741               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4742                 {
4743                   const double *st2=coo+3*st;
4744                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4745                   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]));
4746                   if(pos>eps && pos<1-eps)
4747                     {
4748                       int nNode=((int)addCoo.size())/3;
4749                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4750                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4751                       cut3DCurve[i]=nnodes+nNode;
4752                     }
4753                 }
4754             }
4755         }
4756       else
4757         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4758     }
4759   if(!addCoo.empty())
4760     {
4761       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4762       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4763       coo2->alloc(newNbOfNodes,3);
4764       double *tmp=coo2->getPointer();
4765       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4766       std::copy(addCoo.begin(),addCoo.end(),tmp);
4767       DataArrayDouble::SetArrayIn(coo2,_coords);
4768     }
4769 }
4770
4771 /*!
4772  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4773  * \param mesh1D is the input 1D mesh used for translation computation.
4774  * \return newCoords new coords filled by this method. 
4775  */
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4777 {
4778   int oldNbOfNodes=getNumberOfNodes();
4779   int nbOf1DCells=mesh1D->getNumberOfCells();
4780   int spaceDim=getSpaceDimension();
4781   DataArrayDouble *ret=DataArrayDouble::New();
4782   std::vector<bool> isQuads;
4783   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4784   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4785   double *retPtr=ret->getPointer();
4786   const double *coords=getCoords()->getConstPointer();
4787   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4788   std::vector<int> v;
4789   std::vector<double> c;
4790   double vec[3];
4791   v.reserve(3);
4792   c.reserve(6);
4793   for(int i=0;i<nbOf1DCells;i++)
4794     {
4795       v.resize(0);
4796       mesh1D->getNodeIdsOfCell(i,v);
4797       c.resize(0);
4798       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4799       mesh1D->getCoordinatesOfNode(v[0],c);
4800       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4801       for(int j=0;j<oldNbOfNodes;j++)
4802         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4803       if(isQuad)
4804         {
4805           c.resize(0);
4806           mesh1D->getCoordinatesOfNode(v[1],c);
4807           mesh1D->getCoordinatesOfNode(v[0],c);
4808           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4809           for(int j=0;j<oldNbOfNodes;j++)
4810             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4811         }
4812     }
4813   ret->copyStringInfoFrom(*getCoords());
4814   return ret;
4815 }
4816
4817 /*!
4818  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4819  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4820  * \return newCoords new coords filled by this method. 
4821  */
4822 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4823 {
4824   if(mesh1D->getSpaceDimension()==2)
4825     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4826   if(mesh1D->getSpaceDimension()==3)
4827     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4828   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4829 }
4830
4831 /*!
4832  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4833  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4834  * \return newCoords new coords filled by this method. 
4835  */
4836 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4837 {
4838   if(isQuad)
4839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4840   int oldNbOfNodes=getNumberOfNodes();
4841   int nbOf1DCells=mesh1D->getNumberOfCells();
4842   if(nbOf1DCells<2)
4843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4844   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4845   int nbOfLevsInVec=nbOf1DCells+1;
4846   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4847   double *retPtr=ret->getPointer();
4848   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4849   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4850   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4851   tmp->setCoords(tmp2);
4852   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4853   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4854   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4855   for(int i=1;i<nbOfLevsInVec;i++)
4856     {
4857       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4858       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4859       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4860       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4861       tmp->translate(vec);
4862       double tmp3[2],radius,alpha,alpha0;
4863       const double *p0=i+1<nbOfLevsInVec?begin:third;
4864       const double *p1=i+1<nbOfLevsInVec?end:begin;
4865       const double *p2=i+1<nbOfLevsInVec?third:end;
4866       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4867       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]);
4868       double angle=acos(cosangle/(radius*radius));
4869       tmp->rotate(end,0,angle);
4870       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4871     }
4872   return ret.retn();
4873 }
4874
4875 /*!
4876  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4877  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4878  * \return newCoords new coords filled by this method. 
4879  */
4880 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4881 {
4882   if(isQuad)
4883     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4884   int oldNbOfNodes=getNumberOfNodes();
4885   int nbOf1DCells=mesh1D->getNumberOfCells();
4886   if(nbOf1DCells<2)
4887     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4888   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4889   int nbOfLevsInVec=nbOf1DCells+1;
4890   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4891   double *retPtr=ret->getPointer();
4892   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4893   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4894   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4895   tmp->setCoords(tmp2);
4896   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4897   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4898   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4899   for(int i=1;i<nbOfLevsInVec;i++)
4900     {
4901       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4902       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4903       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4904       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4905       tmp->translate(vec);
4906       double tmp3[2],radius,alpha,alpha0;
4907       const double *p0=i+1<nbOfLevsInVec?begin:third;
4908       const double *p1=i+1<nbOfLevsInVec?end:begin;
4909       const double *p2=i+1<nbOfLevsInVec?third:end;
4910       double vecPlane[3]={
4911         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4912         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4913         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4914       };
4915       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4916       if(norm>1.e-7)
4917         {
4918           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4919           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4920           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4921           double s2=norm2;
4922           double c2=cos(asin(s2));
4923           double m[3][3]={
4924             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4925             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4926             {-vec2[1]*s2, vec2[0]*s2, c2}
4927           };
4928           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]};
4929           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]};
4930           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]};
4931           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4932           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]);
4933           double angle=acos(cosangle/(radius*radius));
4934           tmp->rotate(end,vecPlane,angle);
4935         }
4936       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4937     }
4938   return ret.retn();
4939 }
4940
4941 /*!
4942  * This method is private because not easy to use for end user. This method is const contrary to
4943  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4944  * the coords sorted slice by slice.
4945  * \param isQuad specifies presence of quadratic cells.
4946  */
4947 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4948 {
4949   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4950   int nbOf2DCells(getNumberOfCells());
4951   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4952   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4953   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4954   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4955   newConnI->alloc(nbOf3DCells+1,1);
4956   int *newConnIPtr(newConnI->getPointer());
4957   *newConnIPtr++=0;
4958   std::vector<int> newc;
4959   for(int j=0;j<nbOf2DCells;j++)
4960     {
4961       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4962       *newConnIPtr++=(int)newc.size();
4963     }
4964   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4965   int *newConnPtr(newConn->getPointer());
4966   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4967   newConnIPtr=newConnI->getPointer();
4968   for(int iz=0;iz<nbOf1DCells;iz++)
4969     {
4970       if(iz!=0)
4971         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4972       const int *posOfTypeOfCell(newConnIPtr);
4973       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4974         {
4975           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4976           if(icell!=*posOfTypeOfCell)
4977             {
4978               if(*iter!=-1)
4979                 *newConnPtr=(*iter)+iz*deltaPerLev;
4980               else
4981                 *newConnPtr=-1;
4982             }
4983           else
4984             {
4985               *newConnPtr=*iter;
4986               posOfTypeOfCell++;
4987             }
4988         }
4989     }
4990   ret->setConnectivity(newConn,newConnI,true);
4991   ret->setCoords(getCoords());
4992   return ret;
4993 }
4994
4995 /*!
4996  * Checks if \a this mesh is constituted by only quadratic cells.
4997  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4998  *  \throw If the coordinates array is not set.
4999  *  \throw If the nodal connectivity of cells is not defined.
5000  */
5001 bool MEDCouplingUMesh::isFullyQuadratic() const
5002 {
5003   checkFullyDefined();
5004   bool ret=true;
5005   int nbOfCells=getNumberOfCells();
5006   for(int i=0;i<nbOfCells && ret;i++)
5007     {
5008       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5009       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5010       ret=cm.isQuadratic();
5011     }
5012   return ret;
5013 }
5014
5015 /*!
5016  * Checks if \a this mesh includes any quadratic cell.
5017  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5018  *  \throw If the coordinates array is not set.
5019  *  \throw If the nodal connectivity of cells is not defined.
5020  */
5021 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5022 {
5023   checkFullyDefined();
5024   bool ret=false;
5025   int nbOfCells=getNumberOfCells();
5026   for(int i=0;i<nbOfCells && !ret;i++)
5027     {
5028       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5029       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030       ret=cm.isQuadratic();
5031     }
5032   return ret;
5033 }
5034
5035 /*!
5036  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5037  * this mesh, it remains unchanged.
5038  *  \throw If the coordinates array is not set.
5039  *  \throw If the nodal connectivity of cells is not defined.
5040  */
5041 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5042 {
5043   checkFullyDefined();
5044   int nbOfCells=getNumberOfCells();
5045   int delta=0;
5046   const int *iciptr=_nodal_connec_index->getConstPointer();
5047   for(int i=0;i<nbOfCells;i++)
5048     {
5049       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5050       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5051       if(cm.isQuadratic())
5052         {
5053           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5054           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5055           if(!cml.isDynamic())
5056             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5057           else
5058             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5059         }
5060     }
5061   if(delta==0)
5062     return ;
5063   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5064   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5065   const int *icptr=_nodal_connec->getConstPointer();
5066   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5067   newConnI->alloc(nbOfCells+1,1);
5068   int *ocptr=newConn->getPointer();
5069   int *ociptr=newConnI->getPointer();
5070   *ociptr=0;
5071   _types.clear();
5072   for(int i=0;i<nbOfCells;i++,ociptr++)
5073     {
5074       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5075       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5076       if(!cm.isQuadratic())
5077         {
5078           _types.insert(type);
5079           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5080           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5081         }
5082       else
5083         {
5084           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5085           _types.insert(typel);
5086           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5087           int newNbOfNodes=cml.getNumberOfNodes();
5088           if(cml.isDynamic())
5089             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5090           *ocptr++=(int)typel;
5091           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5092           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5093         }
5094     }
5095   setConnectivity(newConn,newConnI,false);
5096 }
5097
5098 /*!
5099  * This method converts all linear cell in \a this to quadratic one.
5100  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5101  * 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)
5102  * 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.
5103  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5104  * end of the existing coordinates.
5105  * 
5106  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5107  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5108  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5109  * 
5110  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5111  *
5112  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5113  */
5114 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5115 {
5116   DataArrayInt *conn=0,*connI=0;
5117   DataArrayDouble *coords=0;
5118   std::set<INTERP_KERNEL::NormalizedCellType> types;
5119   checkFullyDefined();
5120   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5121   MCAuto<DataArrayDouble> coordsSafe;
5122   int meshDim=getMeshDimension();
5123   switch(conversionType)
5124   {
5125     case 0:
5126       switch(meshDim)
5127       {
5128         case 1:
5129           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5130           connSafe=conn; connISafe=connI; coordsSafe=coords;
5131           break;
5132         case 2:
5133           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5134           connSafe=conn; connISafe=connI; coordsSafe=coords;
5135           break;
5136         case 3:
5137           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5138           connSafe=conn; connISafe=connI; coordsSafe=coords;
5139           break;
5140         default:
5141           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5142       }
5143       break;
5144         case 1:
5145           {
5146             switch(meshDim)
5147             {
5148               case 1:
5149                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5150                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5151                 break;
5152               case 2:
5153                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5154                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5155                 break;
5156               case 3:
5157                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5158                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5159                 break;
5160               default:
5161                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5162             }
5163             break;
5164           }
5165         default:
5166           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5167   }
5168   setConnectivity(connSafe,connISafe,false);
5169   _types=types;
5170   setCoords(coordsSafe);
5171   return ret.retn();
5172 }
5173
5174 /*!
5175  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5176  * so that the number of cells remains the same. Quadratic faces are converted to
5177  * polygons. This method works only for 2D meshes in
5178  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5179  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5180  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5181  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5182  *         a polylinized edge constituting the input polygon.
5183  *  \throw If the coordinates array is not set.
5184  *  \throw If the nodal connectivity of cells is not defined.
5185  *  \throw If \a this->getMeshDimension() != 2.
5186  *  \throw If \a this->getSpaceDimension() != 2.
5187  */
5188 void MEDCouplingUMesh::tessellate2D(double eps)
5189 {
5190   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5191   if(spaceDim!=2)
5192     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5193   switch(meshDim)
5194     {
5195     case 1:
5196       return tessellate2DCurveInternal(eps);
5197     case 2:
5198       return tessellate2DInternal(eps);
5199     default:
5200       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5201     }
5202 }
5203 /*!
5204  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5205  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5206  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5207  *         a sub-divided edge.
5208  *  \throw If the coordinates array is not set.
5209  *  \throw If the nodal connectivity of cells is not defined.
5210  *  \throw If \a this->getMeshDimension() != 1.
5211  *  \throw If \a this->getSpaceDimension() != 2.
5212  */
5213
5214 #if 0
5215 /*!
5216  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5217  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5218  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5219  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5220  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5221  * This method can be seen as the opposite method of colinearize2D.
5222  * 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
5223  * to avoid to modify the numbering of existing nodes.
5224  *
5225  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5226  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5227  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5228  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5229  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5230  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5231  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5232  *
5233  * \sa buildDescendingConnectivity2
5234  */
5235 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5236                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5237 {
5238   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5240   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5241   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5243   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5245   //DataArrayInt *out0(0),*outi0(0);
5246   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5247   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5248   //out0s=out0s->buildUnique(); out0s->sort(true);
5249 }
5250 #endif
5251
5252 /*!
5253  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256  */
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 {
5259   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5260   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5261   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5262   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5263   int nbOfCells=getNumberOfCells();
5264   int nbOfNodes=getNumberOfNodes();
5265   const int *cPtr=_nodal_connec->getConstPointer();
5266   const int *icPtr=_nodal_connec_index->getConstPointer();
5267   int lastVal=0,offset=nbOfNodes;
5268   for(int i=0;i<nbOfCells;i++,icPtr++)
5269     {
5270       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5271       if(type==INTERP_KERNEL::NORM_SEG2)
5272         {
5273           types.insert(INTERP_KERNEL::NORM_SEG3);
5274           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5275           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5276           newConn->pushBackSilent(offset++);
5277           lastVal+=4;
5278           newConnI->pushBackSilent(lastVal);
5279           ret->pushBackSilent(i);
5280         }
5281       else
5282         {
5283           types.insert(type);
5284           lastVal+=(icPtr[1]-icPtr[0]);
5285           newConnI->pushBackSilent(lastVal);
5286           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5287         }
5288     }
5289   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5290   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5291   return ret.retn();
5292 }
5293
5294 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
5295 {
5296   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5297   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5298   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5299   //
5300   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5301   DataArrayInt *conn1D=0,*conn1DI=0;
5302   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5303   DataArrayDouble *coordsTmp=0;
5304   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5305   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5306   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5307   const int *c1DPtr=conn1D->begin();
5308   const int *c1DIPtr=conn1DI->begin();
5309   int nbOfCells=getNumberOfCells();
5310   const int *cPtr=_nodal_connec->getConstPointer();
5311   const int *icPtr=_nodal_connec_index->getConstPointer();
5312   int lastVal=0;
5313   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5314     {
5315       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5316       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5317       if(!cm.isQuadratic())
5318         {
5319           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5320           types.insert(typ2); newConn->pushBackSilent(typ2);
5321           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5322           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5323             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5324           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5325           newConnI->pushBackSilent(lastVal);
5326           ret->pushBackSilent(i);
5327         }
5328       else
5329         {
5330           types.insert(typ);
5331           lastVal+=(icPtr[1]-icPtr[0]);
5332           newConnI->pushBackSilent(lastVal);
5333           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5334         }
5335     }
5336   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5337   return ret.retn();
5338 }
5339
5340 /*!
5341  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5342  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5343  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5344  */
5345 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5346 {
5347   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5348   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5349   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5350 }
5351
5352 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5353 {
5354   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5355   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5356   //
5357   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5358   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5359   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5360   //
5361   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5362   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5363   DataArrayInt *conn1D=0,*conn1DI=0;
5364   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5365   DataArrayDouble *coordsTmp=0;
5366   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5367   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5368   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5369   const int *c1DPtr=conn1D->begin();
5370   const int *c1DIPtr=conn1DI->begin();
5371   int nbOfCells=getNumberOfCells();
5372   const int *cPtr=_nodal_connec->getConstPointer();
5373   const int *icPtr=_nodal_connec_index->getConstPointer();
5374   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5375   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5376     {
5377       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5378       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5379       if(!cm.isQuadratic())
5380         {
5381           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5382           types.insert(typ2); newConn->pushBackSilent(typ2);
5383           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5384           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5385             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5386           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5387           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5388           newConnI->pushBackSilent(lastVal);
5389           ret->pushBackSilent(i);
5390         }
5391       else
5392         {
5393           types.insert(typ);
5394           lastVal+=(icPtr[1]-icPtr[0]);
5395           newConnI->pushBackSilent(lastVal);
5396           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5397         }
5398     }
5399   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5400   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5401   return ret.retn();
5402 }
5403
5404 /*!
5405  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5406  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5407  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5408  */
5409 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5410 {
5411   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5412   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5413   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5414 }
5415
5416 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5417 {
5418   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5419   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5420   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5421   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5422   //
5423   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5424   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5425   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5426   //
5427   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5428   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5429   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5430   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5431   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5432   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5433   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5434   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5435   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5436   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5437   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5438   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5439   int nbOfCells=getNumberOfCells();
5440   const int *cPtr=_nodal_connec->getConstPointer();
5441   const int *icPtr=_nodal_connec_index->getConstPointer();
5442   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5443   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5444     {
5445       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5446       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5447       if(!cm.isQuadratic())
5448         {
5449           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5450           if(typ2==INTERP_KERNEL::NORM_ERROR)
5451             {
5452               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5453               throw INTERP_KERNEL::Exception(oss.str().c_str());
5454             }
5455           types.insert(typ2); newConn->pushBackSilent(typ2);
5456           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5457           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5458             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5459           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5460             {
5461               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5462               int tmpPos=newConn->getNumberOfTuples();
5463               newConn->pushBackSilent(nodeId2);
5464               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5465             }
5466           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5467           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5468           newConnI->pushBackSilent(lastVal);
5469           ret->pushBackSilent(i);
5470         }
5471       else
5472         {
5473           types.insert(typ);
5474           lastVal+=(icPtr[1]-icPtr[0]);
5475           newConnI->pushBackSilent(lastVal);
5476           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5477         }
5478     }
5479   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5480   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5481   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5482   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5483   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5484   int *c=newConn->getPointer();
5485   const int *cI(newConnI->begin());
5486   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5487     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5488   offset=coordsTmp2Safe->getNumberOfTuples();
5489   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5490     c[cI[(*elt)+1]-1]+=offset;
5491   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5492   return ret.retn();
5493 }
5494
5495 /*!
5496  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5497  * In addition, returns an array mapping new cells to old ones. <br>
5498  * This method typically increases the number of cells in \a this mesh
5499  * but the number of nodes remains \b unchanged.
5500  * That's why the 3D splitting policies
5501  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5502  *  \param [in] policy - specifies a pattern used for splitting.
5503  * The semantic of \a policy is:
5504  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5505  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5506  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5507  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5508  *
5509  *
5510  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5511  *          an id of old cell producing it. The caller is to delete this array using
5512  *         decrRef() as it is no more needed.
5513  *
5514  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5515  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5516  *          and \a this->getMeshDimension() != 3. 
5517  *  \throw If \a policy is not one of the four discussed above.
5518  *  \throw If the nodal connectivity of cells is not defined.
5519  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5520  */
5521 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5522 {
5523   switch(policy)
5524   {
5525     case 0:
5526       return simplexizePol0();
5527     case 1:
5528       return simplexizePol1();
5529     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5530         return simplexizePlanarFace5();
5531     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5532         return simplexizePlanarFace6();
5533     default:
5534       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)");
5535   }
5536 }
5537
5538 /*!
5539  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5540  * - 1D: INTERP_KERNEL::NORM_SEG2
5541  * - 2D: INTERP_KERNEL::NORM_TRI3
5542  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5543  *
5544  * This method is useful for users that need to use P1 field services as
5545  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5546  * All these methods need mesh support containing only simplex cells.
5547  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5548  *  \throw If the coordinates array is not set.
5549  *  \throw If the nodal connectivity of cells is not defined.
5550  *  \throw If \a this->getMeshDimension() < 1.
5551  */
5552 bool MEDCouplingUMesh::areOnlySimplexCells() const
5553 {
5554   checkFullyDefined();
5555   int mdim=getMeshDimension();
5556   if(mdim<1 || mdim>3)
5557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5558   int nbCells=getNumberOfCells();
5559   const int *conn=_nodal_connec->getConstPointer();
5560   const int *connI=_nodal_connec_index->getConstPointer();
5561   for(int i=0;i<nbCells;i++)
5562     {
5563       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5564       if(!cm.isSimplex())
5565         return false;
5566     }
5567   return true;
5568 }
5569
5570 /*!
5571  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5572  */
5573 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5574 {
5575   checkConnectivityFullyDefined();
5576   if(getMeshDimension()!=2)
5577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5578   int nbOfCells=getNumberOfCells();
5579   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5580   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5581   ret->alloc(nbOfCells+nbOfCutCells,1);
5582   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5583   int *retPt=ret->getPointer();
5584   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5585   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5586   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5587   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5588   int *pt=newConn->getPointer();
5589   int *ptI=newConnI->getPointer();
5590   ptI[0]=0;
5591   const int *oldc=_nodal_connec->getConstPointer();
5592   const int *ci=_nodal_connec_index->getConstPointer();
5593   for(int i=0;i<nbOfCells;i++,ci++)
5594     {
5595       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5596         {
5597           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5598             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5599           pt=std::copy(tmp,tmp+8,pt);
5600           ptI[1]=ptI[0]+4;
5601           ptI[2]=ptI[0]+8;
5602           *retPt++=i;
5603           *retPt++=i;
5604           ptI+=2;
5605         }
5606       else
5607         {
5608           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5609           ptI[1]=ptI[0]+ci[1]-ci[0];
5610           ptI++;
5611           *retPt++=i;
5612         }
5613     }
5614   _nodal_connec->decrRef();
5615   _nodal_connec=newConn.retn();
5616   _nodal_connec_index->decrRef();
5617   _nodal_connec_index=newConnI.retn();
5618   computeTypes();
5619   updateTime();
5620   return ret.retn();
5621 }
5622
5623 /*!
5624  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5625  */
5626 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5627 {
5628   checkConnectivityFullyDefined();
5629   if(getMeshDimension()!=2)
5630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5631   int nbOfCells=getNumberOfCells();
5632   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5633   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5634   ret->alloc(nbOfCells+nbOfCutCells,1);
5635   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5636   int *retPt=ret->getPointer();
5637   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5638   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5639   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5640   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5641   int *pt=newConn->getPointer();
5642   int *ptI=newConnI->getPointer();
5643   ptI[0]=0;
5644   const int *oldc=_nodal_connec->getConstPointer();
5645   const int *ci=_nodal_connec_index->getConstPointer();
5646   for(int i=0;i<nbOfCells;i++,ci++)
5647     {
5648       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5649         {
5650           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5651             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5652           pt=std::copy(tmp,tmp+8,pt);
5653           ptI[1]=ptI[0]+4;
5654           ptI[2]=ptI[0]+8;
5655           *retPt++=i;
5656           *retPt++=i;
5657           ptI+=2;
5658         }
5659       else
5660         {
5661           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5662           ptI[1]=ptI[0]+ci[1]-ci[0];
5663           ptI++;
5664           *retPt++=i;
5665         }
5666     }
5667   _nodal_connec->decrRef();
5668   _nodal_connec=newConn.retn();
5669   _nodal_connec_index->decrRef();
5670   _nodal_connec_index=newConnI.retn();
5671   computeTypes();
5672   updateTime();
5673   return ret.retn();
5674 }
5675
5676 /*!
5677  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5678  */
5679 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5680 {
5681   checkConnectivityFullyDefined();
5682   if(getMeshDimension()!=3)
5683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5684   int nbOfCells=getNumberOfCells();
5685   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5686   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5687   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5688   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5689   int *retPt=ret->getPointer();
5690   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5691   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5692   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5693   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5694   int *pt=newConn->getPointer();
5695   int *ptI=newConnI->getPointer();
5696   ptI[0]=0;
5697   const int *oldc=_nodal_connec->getConstPointer();
5698   const int *ci=_nodal_connec_index->getConstPointer();
5699   for(int i=0;i<nbOfCells;i++,ci++)
5700     {
5701       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5702         {
5703           for(int j=0;j<5;j++,pt+=5,ptI++)
5704             {
5705               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5706               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];
5707               *retPt++=i;
5708               ptI[1]=ptI[0]+5;
5709             }
5710         }
5711       else
5712         {
5713           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5714           ptI[1]=ptI[0]+ci[1]-ci[0];
5715           ptI++;
5716           *retPt++=i;
5717         }
5718     }
5719   _nodal_connec->decrRef();
5720   _nodal_connec=newConn.retn();
5721   _nodal_connec_index->decrRef();
5722   _nodal_connec_index=newConnI.retn();
5723   computeTypes();
5724   updateTime();
5725   return ret.retn();
5726 }
5727
5728 /*!
5729  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5730  */
5731 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5732 {
5733   checkConnectivityFullyDefined();
5734   if(getMeshDimension()!=3)
5735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5736   int nbOfCells=getNumberOfCells();
5737   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5738   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5739   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5740   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5741   int *retPt=ret->getPointer();
5742   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5743   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5744   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5745   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5746   int *pt=newConn->getPointer();
5747   int *ptI=newConnI->getPointer();
5748   ptI[0]=0;
5749   const int *oldc=_nodal_connec->getConstPointer();
5750   const int *ci=_nodal_connec_index->getConstPointer();
5751   for(int i=0;i<nbOfCells;i++,ci++)
5752     {
5753       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5754         {
5755           for(int j=0;j<6;j++,pt+=5,ptI++)
5756             {
5757               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5758               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];
5759               *retPt++=i;
5760               ptI[1]=ptI[0]+5;
5761             }
5762         }
5763       else
5764         {
5765           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5766           ptI[1]=ptI[0]+ci[1]-ci[0];
5767           ptI++;
5768           *retPt++=i;
5769         }
5770     }
5771   _nodal_connec->decrRef();
5772   _nodal_connec=newConn.retn();
5773   _nodal_connec_index->decrRef();
5774   _nodal_connec_index=newConnI.retn();
5775   computeTypes();
5776   updateTime();
5777   return ret.retn();
5778 }
5779
5780 /*!
5781  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5782  * so that the number of cells remains the same. Quadratic faces are converted to
5783  * polygons. This method works only for 2D meshes in
5784  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5785  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5786  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5787  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5788  *         a polylinized edge constituting the input polygon.
5789  *  \throw If the coordinates array is not set.
5790  *  \throw If the nodal connectivity of cells is not defined.
5791  *  \throw If \a this->getMeshDimension() != 2.
5792  *  \throw If \a this->getSpaceDimension() != 2.
5793  */
5794 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5795 {
5796   checkFullyDefined();
5797   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5799   double epsa=fabs(eps);
5800   if(epsa<std::numeric_limits<double>::min())
5801     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5802   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5803   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5804   revDesc1=0; revDescIndx1=0;
5805   mDesc->tessellate2D(eps);
5806   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5807   setCoords(mDesc->getCoords());
5808 }
5809
5810 /*!
5811  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5812  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5813  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5814  *         a sub-divided edge.
5815  *  \throw If the coordinates array is not set.
5816  *  \throw If the nodal connectivity of cells is not defined.
5817  *  \throw If \a this->getMeshDimension() != 1.
5818  *  \throw If \a this->getSpaceDimension() != 2.
5819  */
5820 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5821 {
5822   checkFullyDefined();
5823   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5825   double epsa=fabs(eps);
5826   if(epsa<std::numeric_limits<double>::min())
5827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5828   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5829   int nbCells=getNumberOfCells();
5830   int nbNodes=getNumberOfNodes();
5831   const int *conn=_nodal_connec->getConstPointer();
5832   const int *connI=_nodal_connec_index->getConstPointer();
5833   const double *coords=_coords->getConstPointer();
5834   std::vector<double> addCoo;
5835   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5836   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
5837   newConnI->alloc(nbCells+1,1);
5838   int *newConnIPtr=newConnI->getPointer();
5839   *newConnIPtr=0;
5840   int tmp1[3];
5841   INTERP_KERNEL::Node *tmp2[3];
5842   std::set<INTERP_KERNEL::NormalizedCellType> types;
5843   for(int i=0;i<nbCells;i++,newConnIPtr++)
5844     {
5845       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5846       if(cm.isQuadratic())
5847         {//assert(connI[i+1]-connI[i]-1==3)
5848           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5849           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5850           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5851           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5852           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5853           if(eac)
5854             {
5855               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5856               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5857               delete eac;
5858               newConnIPtr[1]=(int)newConn.size();
5859             }
5860           else
5861             {
5862               types.insert(INTERP_KERNEL::NORM_SEG2);
5863               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5864               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5865               newConnIPtr[1]=newConnIPtr[0]+3;
5866             }
5867         }
5868       else
5869         {
5870           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5871           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5872           newConnIPtr[1]=newConnIPtr[0]+3;
5873         }
5874     }
5875   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5876     return ;
5877   _types=types;
5878   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5879   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
5880   newConnArr->alloc((int)newConn.size(),1);
5881   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5882   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5883   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
5884   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5885   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5886   std::copy(addCoo.begin(),addCoo.end(),work);
5887   DataArrayDouble::SetArrayIn(newCoords,_coords);
5888   updateTime();
5889 }
5890
5891 /*!
5892  * 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.
5893  * This method completly ignore coordinates.
5894  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5895  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5896  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5897  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5898  */
5899 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5900 {
5901   checkFullyDefined();
5902   if(getMeshDimension()!=2)
5903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5904   int nbOfCells=getNumberOfCells();
5905   int *connI=_nodal_connec_index->getPointer();
5906   int newConnLgth=0;
5907   for(int i=0;i<nbOfCells;i++,connI++)
5908     {
5909       int offset=descIndex[i];
5910       int nbOfEdges=descIndex[i+1]-offset;
5911       //
5912       bool ddirect=desc[offset+nbOfEdges-1]>0;
5913       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5914       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5915       for(int j=0;j<nbOfEdges;j++)
5916         {
5917           bool direct=desc[offset+j]>0;
5918           int edgeId=std::abs(desc[offset+j])-1;
5919           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5920             {
5921               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5922               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5923               int ref2=direct?id1:id2;
5924               if(ref==ref2)
5925                 {
5926                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5927                   newConnLgth+=nbOfSubNodes-1;
5928                   ref=direct?id2:id1;
5929                 }
5930               else
5931                 {
5932                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5933                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5934                 }
5935             }
5936           else
5937             {
5938               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5939             }
5940         }
5941       newConnLgth++;//+1 is for cell type
5942       connI[1]=newConnLgth;
5943     }
5944   //
5945   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5946   newConn->alloc(newConnLgth,1);
5947   int *work=newConn->getPointer();
5948   for(int i=0;i<nbOfCells;i++)
5949     {
5950       *work++=INTERP_KERNEL::NORM_POLYGON;
5951       int offset=descIndex[i];
5952       int nbOfEdges=descIndex[i+1]-offset;
5953       for(int j=0;j<nbOfEdges;j++)
5954         {
5955           bool direct=desc[offset+j]>0;
5956           int edgeId=std::abs(desc[offset+j])-1;
5957           if(direct)
5958             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5959           else
5960             {
5961               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5962               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5963               work=std::copy(it,it+nbOfSubNodes-1,work);
5964             }
5965         }
5966     }
5967   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5968   _types.clear();
5969   if(nbOfCells>0)
5970     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5971 }
5972
5973 /*!
5974  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5975  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5976  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5977  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5978  * so it can be useful to call mergeNodes() before calling this method.
5979  *  \throw If \a this->getMeshDimension() <= 1.
5980  *  \throw If the coordinates array is not set.
5981  *  \throw If the nodal connectivity of cells is not defined.
5982  */
5983 void MEDCouplingUMesh::convertDegeneratedCells()
5984 {
5985   checkFullyDefined();
5986   if(getMeshDimension()<=1)
5987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5988   int nbOfCells=getNumberOfCells();
5989   if(nbOfCells<1)
5990     return ;
5991   int initMeshLgth=getNodalConnectivityArrayLen();
5992   int *conn=_nodal_connec->getPointer();
5993   int *index=_nodal_connec_index->getPointer();
5994   int posOfCurCell=0;
5995   int newPos=0;
5996   int lgthOfCurCell;
5997   for(int i=0;i<nbOfCells;i++)
5998     {
5999       lgthOfCurCell=index[i+1]-posOfCurCell;
6000       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6001       int newLgth;
6002       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6003                                                                                                      conn+newPos+1,newLgth);
6004       conn[newPos]=newType;
6005       newPos+=newLgth+1;
6006       posOfCurCell=index[i+1];
6007       index[i+1]=newPos;
6008     }
6009   if(newPos!=initMeshLgth)
6010     _nodal_connec->reAlloc(newPos);
6011   computeTypes();
6012 }
6013
6014 /*!
6015  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6016  * A cell is considered to be oriented correctly if an angle between its
6017  * normal vector and a given vector is less than \c PI / \c 2.
6018  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6019  *         cells. 
6020  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6021  *         checked.
6022  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6023  *         is not cleared before filling in.
6024  *  \throw If \a this->getMeshDimension() != 2.
6025  *  \throw If \a this->getSpaceDimension() != 3.
6026  *
6027  *  \if ENABLE_EXAMPLES
6028  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6029  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6030  *  \endif
6031  */
6032 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6033 {
6034   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6035     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6036   int nbOfCells=getNumberOfCells();
6037   const int *conn=_nodal_connec->getConstPointer();
6038   const int *connI=_nodal_connec_index->getConstPointer();
6039   const double *coordsPtr=_coords->getConstPointer();
6040   for(int i=0;i<nbOfCells;i++)
6041     {
6042       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6043       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6044         {
6045           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6046           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6047             cells.push_back(i);
6048         }
6049     }
6050 }
6051
6052 /*!
6053  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6054  * considered to be oriented correctly if an angle between its normal vector and a
6055  * given vector is less than \c PI / \c 2. 
6056  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6057  *         cells. 
6058  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6059  *         checked.
6060  *  \throw If \a this->getMeshDimension() != 2.
6061  *  \throw If \a this->getSpaceDimension() != 3.
6062  *
6063  *  \if ENABLE_EXAMPLES
6064  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6065  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6066  *  \endif
6067  *
6068  *  \sa changeOrientationOfCells
6069  */
6070 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6071 {
6072   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6073     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6074   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6075   const int *connI(_nodal_connec_index->getConstPointer());
6076   const double *coordsPtr(_coords->getConstPointer());
6077   bool isModified(false);
6078   for(int i=0;i<nbOfCells;i++)
6079     {
6080       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6081       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6082         {
6083           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6084           bool isQuadratic(cm.isQuadratic());
6085           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6086             {
6087               isModified=true;
6088               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6089             }
6090         }
6091     }
6092   if(isModified)
6093     _nodal_connec->declareAsNew();
6094   updateTime();
6095 }
6096
6097 /*!
6098  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6099  *
6100  * \sa orientCorrectly2DCells
6101  */
6102 void MEDCouplingUMesh::changeOrientationOfCells()
6103 {
6104   int mdim(getMeshDimension());
6105   if(mdim!=2 && mdim!=1)
6106     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6107   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6108   const int *connI(_nodal_connec_index->getConstPointer());
6109   if(mdim==2)
6110     {//2D
6111       for(int i=0;i<nbOfCells;i++)
6112         {
6113           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6114           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6115           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6116         }
6117     }
6118   else
6119     {//1D
6120       for(int i=0;i<nbOfCells;i++)
6121         {
6122           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6123           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6124           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6125         }
6126     }
6127 }
6128
6129 /*!
6130  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6131  * oriented facets. The normal vector of the facet should point out of the cell.
6132  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6133  *         is not cleared before filling in.
6134  *  \throw If \a this->getMeshDimension() != 3.
6135  *  \throw If \a this->getSpaceDimension() != 3.
6136  *  \throw If the coordinates array is not set.
6137  *  \throw If the nodal connectivity of cells is not defined.
6138  *
6139  *  \if ENABLE_EXAMPLES
6140  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6141  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6142  *  \endif
6143  */
6144 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6145 {
6146   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6147     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6148   int nbOfCells=getNumberOfCells();
6149   const int *conn=_nodal_connec->getConstPointer();
6150   const int *connI=_nodal_connec_index->getConstPointer();
6151   const double *coordsPtr=_coords->getConstPointer();
6152   for(int i=0;i<nbOfCells;i++)
6153     {
6154       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6155       if(type==INTERP_KERNEL::NORM_POLYHED)
6156         {
6157           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6158             cells.push_back(i);
6159         }
6160     }
6161 }
6162
6163 /*!
6164  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6165  * out of the cell. 
6166  *  \throw If \a this->getMeshDimension() != 3.
6167  *  \throw If \a this->getSpaceDimension() != 3.
6168  *  \throw If the coordinates array is not set.
6169  *  \throw If the nodal connectivity of cells is not defined.
6170  *  \throw If the reparation fails.
6171  *
6172  *  \if ENABLE_EXAMPLES
6173  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6174  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6175  *  \endif
6176  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6177  */
6178 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6179 {
6180   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6181     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6182   int nbOfCells=getNumberOfCells();
6183   int *conn=_nodal_connec->getPointer();
6184   const int *connI=_nodal_connec_index->getConstPointer();
6185   const double *coordsPtr=_coords->getConstPointer();
6186   for(int i=0;i<nbOfCells;i++)
6187     {
6188       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6189       if(type==INTERP_KERNEL::NORM_POLYHED)
6190         {
6191           try
6192           {
6193               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6194                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6195           }
6196           catch(INTERP_KERNEL::Exception& e)
6197           {
6198               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6199               throw INTERP_KERNEL::Exception(oss.str().c_str());
6200           }
6201         }
6202     }
6203   updateTime();
6204 }
6205
6206 /*!
6207  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6208  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6209  * according to which the first facet of the cell should be oriented to have the normal vector
6210  * pointing out of cell.
6211  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6212  *         cells. The caller is to delete this array using decrRef() as it is no more
6213  *         needed. 
6214  *  \throw If \a this->getMeshDimension() != 3.
6215  *  \throw If \a this->getSpaceDimension() != 3.
6216  *  \throw If the coordinates array is not set.
6217  *  \throw If the nodal connectivity of cells is not defined.
6218  *
6219  *  \if ENABLE_EXAMPLES
6220  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6221  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6222  *  \endif
6223  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6224  */
6225 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6226 {
6227   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6228   if(getMeshDimension()!=3)
6229     throw INTERP_KERNEL::Exception(msg);
6230   int spaceDim=getSpaceDimension();
6231   if(spaceDim!=3)
6232     throw INTERP_KERNEL::Exception(msg);
6233   //
6234   int nbOfCells=getNumberOfCells();
6235   int *conn=_nodal_connec->getPointer();
6236   const int *connI=_nodal_connec_index->getConstPointer();
6237   const double *coo=getCoords()->getConstPointer();
6238   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6239   for(int i=0;i<nbOfCells;i++)
6240     {
6241       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6242       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6243         {
6244           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6245             {
6246               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6247               cells->pushBackSilent(i);
6248             }
6249         }
6250     }
6251   return cells.retn();
6252 }
6253
6254 /*!
6255  * This method is a faster method to correct orientation of all 3D cells in \a this.
6256  * 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.
6257  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6258  * 
6259  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6260  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6261  */
6262 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6263 {
6264   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6265     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6266   int nbOfCells=getNumberOfCells();
6267   int *conn=_nodal_connec->getPointer();
6268   const int *connI=_nodal_connec_index->getConstPointer();
6269   const double *coordsPtr=_coords->getConstPointer();
6270   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6271   for(int i=0;i<nbOfCells;i++)
6272     {
6273       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6274       switch(type)
6275       {
6276         case INTERP_KERNEL::NORM_TETRA4:
6277           {
6278             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6279               {
6280                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6281                 ret->pushBackSilent(i);
6282               }
6283             break;
6284           }
6285         case INTERP_KERNEL::NORM_PYRA5:
6286           {
6287             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6288               {
6289                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6290                 ret->pushBackSilent(i);
6291               }
6292             break;
6293           }
6294         case INTERP_KERNEL::NORM_PENTA6:
6295         case INTERP_KERNEL::NORM_HEXA8:
6296         case INTERP_KERNEL::NORM_HEXGP12:
6297           {
6298             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6299               {
6300                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6301                 ret->pushBackSilent(i);
6302               }
6303             break;
6304           }
6305         case INTERP_KERNEL::NORM_POLYHED:
6306           {
6307             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6308               {
6309                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6310                 ret->pushBackSilent(i);
6311               }
6312             break;
6313           }
6314         default:
6315           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 !");
6316       }
6317     }
6318   updateTime();
6319   return ret.retn();
6320 }
6321
6322 /*!
6323  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6324  * If it is not the case an exception will be thrown.
6325  * This method is fast because the first cell of \a this is used to compute the plane.
6326  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6327  * \param pos output of size at least 3 used to store a point owned of searched plane.
6328  */
6329 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6330 {
6331   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6332     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6333   const int *conn=_nodal_connec->getConstPointer();
6334   const int *connI=_nodal_connec_index->getConstPointer();
6335   const double *coordsPtr=_coords->getConstPointer();
6336   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6337   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6338 }
6339
6340 /*!
6341  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6342  * cells. Currently cells of the following types are treated:
6343  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6344  * For a cell of other type an exception is thrown.
6345  * Space dimension of a 2D mesh can be either 2 or 3.
6346  * The Edge Ratio of a cell \f$t\f$ is: 
6347  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6348  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6349  *  the smallest edge lengths of \f$t\f$.
6350  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6351  *          cells and one time, lying on \a this mesh. The caller is to delete this
6352  *          field using decrRef() as it is no more needed. 
6353  *  \throw If the coordinates array is not set.
6354  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6355  *  \throw If the connectivity data array has more than one component.
6356  *  \throw If the connectivity data array has a named component.
6357  *  \throw If the connectivity index data array has more than one component.
6358  *  \throw If the connectivity index data array has a named component.
6359  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6360  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6361  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6362  */
6363 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6364 {
6365   checkConsistencyLight();
6366   int spaceDim=getSpaceDimension();
6367   int meshDim=getMeshDimension();
6368   if(spaceDim!=2 && spaceDim!=3)
6369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6370   if(meshDim!=2 && meshDim!=3)
6371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6372   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6373   ret->setMesh(this);
6374   int nbOfCells=getNumberOfCells();
6375   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6376   arr->alloc(nbOfCells,1);
6377   double *pt=arr->getPointer();
6378   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6379   const int *conn=_nodal_connec->getConstPointer();
6380   const int *connI=_nodal_connec_index->getConstPointer();
6381   const double *coo=_coords->getConstPointer();
6382   double tmp[12];
6383   for(int i=0;i<nbOfCells;i++,pt++)
6384     {
6385       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6386       switch(t)
6387       {
6388         case INTERP_KERNEL::NORM_TRI3:
6389           {
6390             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6391             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6392             break;
6393           }
6394         case INTERP_KERNEL::NORM_QUAD4:
6395           {
6396             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6397             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6398             break;
6399           }
6400         case INTERP_KERNEL::NORM_TETRA4:
6401           {
6402             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6403             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6404             break;
6405           }
6406         default:
6407           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6408       }
6409       conn+=connI[i+1]-connI[i];
6410     }
6411   ret->setName("EdgeRatio");
6412   ret->synchronizeTimeWithSupport();
6413   return ret.retn();
6414 }
6415
6416 /*!
6417  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6418  * cells. Currently cells of the following types are treated:
6419  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6420  * For a cell of other type an exception is thrown.
6421  * Space dimension of a 2D mesh can be either 2 or 3.
6422  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6423  *          cells and one time, lying on \a this mesh. The caller is to delete this
6424  *          field using decrRef() as it is no more needed. 
6425  *  \throw If the coordinates array is not set.
6426  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6427  *  \throw If the connectivity data array has more than one component.
6428  *  \throw If the connectivity data array has a named component.
6429  *  \throw If the connectivity index data array has more than one component.
6430  *  \throw If the connectivity index data array has a named component.
6431  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6432  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6433  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6434  */
6435 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6436 {
6437   checkConsistencyLight();
6438   int spaceDim=getSpaceDimension();
6439   int meshDim=getMeshDimension();
6440   if(spaceDim!=2 && spaceDim!=3)
6441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6442   if(meshDim!=2 && meshDim!=3)
6443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6444   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6445   ret->setMesh(this);
6446   int nbOfCells=getNumberOfCells();
6447   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6448   arr->alloc(nbOfCells,1);
6449   double *pt=arr->getPointer();
6450   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6451   const int *conn=_nodal_connec->getConstPointer();
6452   const int *connI=_nodal_connec_index->getConstPointer();
6453   const double *coo=_coords->getConstPointer();
6454   double tmp[12];
6455   for(int i=0;i<nbOfCells;i++,pt++)
6456     {
6457       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6458       switch(t)
6459       {
6460         case INTERP_KERNEL::NORM_TRI3:
6461           {
6462             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6463             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6464             break;
6465           }
6466         case INTERP_KERNEL::NORM_QUAD4:
6467           {
6468             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6469             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6470             break;
6471           }
6472         case INTERP_KERNEL::NORM_TETRA4:
6473           {
6474             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6475             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6476             break;
6477           }
6478         default:
6479           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6480       }
6481       conn+=connI[i+1]-connI[i];
6482     }
6483   ret->setName("AspectRatio");
6484   ret->synchronizeTimeWithSupport();
6485   return ret.retn();
6486 }
6487
6488 /*!
6489  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6490  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6491  * treated: INTERP_KERNEL::NORM_QUAD4.
6492  * For a cell of other type an exception is thrown.
6493  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6494  *          cells and one time, lying on \a this mesh. The caller is to delete this
6495  *          field using decrRef() as it is no more needed. 
6496  *  \throw If the coordinates array is not set.
6497  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6498  *  \throw If the connectivity data array has more than one component.
6499  *  \throw If the connectivity data array has a named component.
6500  *  \throw If the connectivity index data array has more than one component.
6501  *  \throw If the connectivity index data array has a named component.
6502  *  \throw If \a this->getMeshDimension() != 2.
6503  *  \throw If \a this->getSpaceDimension() != 3.
6504  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6505  */
6506 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6507 {
6508   checkConsistencyLight();
6509   int spaceDim=getSpaceDimension();
6510   int meshDim=getMeshDimension();
6511   if(spaceDim!=3)
6512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6513   if(meshDim!=2)
6514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6515   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6516   ret->setMesh(this);
6517   int nbOfCells=getNumberOfCells();
6518   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6519   arr->alloc(nbOfCells,1);
6520   double *pt=arr->getPointer();
6521   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6522   const int *conn=_nodal_connec->getConstPointer();
6523   const int *connI=_nodal_connec_index->getConstPointer();
6524   const double *coo=_coords->getConstPointer();
6525   double tmp[12];
6526   for(int i=0;i<nbOfCells;i++,pt++)
6527     {
6528       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6529       switch(t)
6530       {
6531         case INTERP_KERNEL::NORM_QUAD4:
6532           {
6533             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6534             *pt=INTERP_KERNEL::quadWarp(tmp);
6535             break;
6536           }
6537         default:
6538           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6539       }
6540       conn+=connI[i+1]-connI[i];
6541     }
6542   ret->setName("Warp");
6543   ret->synchronizeTimeWithSupport();
6544   return ret.retn();
6545 }
6546
6547
6548 /*!
6549  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6550  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6551  * treated: INTERP_KERNEL::NORM_QUAD4.
6552  * The skew is computed as follow for a quad with points (a,b,c,d): let
6553  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
6554  * then the skew is computed as:
6555  *  \f$s=\frac{u}{|u|}\cdot\frac{v}{|v|}\f$
6556  *
6557  * For a cell of other type an exception is thrown.
6558  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6559  *          cells and one time, lying on \a this mesh. The caller is to delete this
6560  *          field using decrRef() as it is no more needed. 
6561  *  \throw If the coordinates array is not set.
6562  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6563  *  \throw If the connectivity data array has more than one component.
6564  *  \throw If the connectivity data array has a named component.
6565  *  \throw If the connectivity index data array has more than one component.
6566  *  \throw If the connectivity index data array has a named component.
6567  *  \throw If \a this->getMeshDimension() != 2.
6568  *  \throw If \a this->getSpaceDimension() != 3.
6569  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6570  */
6571 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6572 {
6573   checkConsistencyLight();
6574   int spaceDim=getSpaceDimension();
6575   int meshDim=getMeshDimension();
6576   if(spaceDim!=3)
6577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6578   if(meshDim!=2)
6579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6580   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6581   ret->setMesh(this);
6582   int nbOfCells=getNumberOfCells();
6583   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6584   arr->alloc(nbOfCells,1);
6585   double *pt=arr->getPointer();
6586   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6587   const int *conn=_nodal_connec->getConstPointer();
6588   const int *connI=_nodal_connec_index->getConstPointer();
6589   const double *coo=_coords->getConstPointer();
6590   double tmp[12];
6591   for(int i=0;i<nbOfCells;i++,pt++)
6592     {
6593       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6594       switch(t)
6595       {
6596         case INTERP_KERNEL::NORM_QUAD4:
6597           {
6598             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6599             *pt=INTERP_KERNEL::quadSkew(tmp);
6600             break;
6601           }
6602         default:
6603           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6604       }
6605       conn+=connI[i+1]-connI[i];
6606     }
6607   ret->setName("Skew");
6608   ret->synchronizeTimeWithSupport();
6609   return ret.retn();
6610 }
6611
6612 /*!
6613  * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
6614  *
6615  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6616  *
6617  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6618  */
6619 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6620 {
6621   checkConsistencyLight();
6622   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6623   ret->setMesh(this);
6624   std::set<INTERP_KERNEL::NormalizedCellType> types;
6625   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6626   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6627   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6628   arr->alloc(nbCells,1);
6629   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6630     {
6631       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6632       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6633       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6634     }
6635   ret->setArray(arr);
6636   ret->setName("Diameter");
6637   return ret.retn();
6638 }
6639
6640 /*!
6641  * This method aggregate the bbox of each cell and put it into bbox parameter.
6642  * 
6643  * \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)
6644  *                         For all other cases this input parameter is ignored.
6645  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6646  * 
6647  * \throw If \a this is not fully set (coordinates and connectivity).
6648  * \throw If a cell in \a this has no valid nodeId.
6649  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6650  */
6651 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6652 {
6653   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6654   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.
6655     return getBoundingBoxForBBTreeFast();
6656   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6657     {
6658       bool presenceOfQuadratic(false);
6659       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6660         {
6661           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6662           if(cm.isQuadratic())
6663             presenceOfQuadratic=true;
6664         }
6665       if(!presenceOfQuadratic)
6666         return getBoundingBoxForBBTreeFast();
6667       if(mDim==2 && sDim==2)
6668         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6669       else
6670         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6671     }
6672   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) !");
6673 }
6674
6675 /*!
6676  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6677  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6678  * 
6679  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6680  * 
6681  * \throw If \a this is not fully set (coordinates and connectivity).
6682  * \throw If a cell in \a this has no valid nodeId.
6683  */
6684 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6685 {
6686   checkFullyDefined();
6687   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6688   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6689   double *bbox(ret->getPointer());
6690   for(int i=0;i<nbOfCells*spaceDim;i++)
6691     {
6692       bbox[2*i]=std::numeric_limits<double>::max();
6693       bbox[2*i+1]=-std::numeric_limits<double>::max();
6694     }
6695   const double *coordsPtr(_coords->getConstPointer());
6696   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6697   for(int i=0;i<nbOfCells;i++)
6698     {
6699       int offset=connI[i]+1;
6700       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6701       for(int j=0;j<nbOfNodesForCell;j++)
6702         {
6703           int nodeId=conn[offset+j];
6704           if(nodeId>=0 && nodeId<nbOfNodes)
6705             {
6706               for(int k=0;k<spaceDim;k++)
6707                 {
6708                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6709                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6710                 }
6711               kk++;
6712             }
6713         }
6714       if(kk==0)
6715         {
6716           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6717           throw INTERP_KERNEL::Exception(oss.str().c_str());
6718         }
6719     }
6720   return ret.retn();
6721 }
6722
6723 /*!
6724  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6725  * useful for 2D meshes having quadratic cells
6726  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6727  * the two extremities of the arc of circle).
6728  * 
6729  * \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)
6730  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6731  * \throw If \a this is not fully defined.
6732  * \throw If \a this is not a mesh with meshDimension equal to 2.
6733  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6734  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6735  */
6736 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6737 {
6738   checkFullyDefined();
6739   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6740   if(spaceDim!=2 || mDim!=2)
6741     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!");
6742   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6743   double *bbox(ret->getPointer());
6744   const double *coords(_coords->getConstPointer());
6745   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6746   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6747     {
6748       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6749       int sz(connI[1]-connI[0]-1);
6750       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6751       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6752       INTERP_KERNEL::QuadraticPolygon *pol(0);
6753       for(int j=0;j<sz;j++)
6754         {
6755           int nodeId(conn[*connI+1+j]);
6756           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6757         }
6758       if(!cm.isQuadratic())
6759         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6760       else
6761         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6762       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6763       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6764     }
6765   return ret.retn();
6766 }
6767
6768 /*!
6769  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6770  * useful for 2D meshes having quadratic cells
6771  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6772  * the two extremities of the arc of circle).
6773  * 
6774  * \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)
6775  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6776  * \throw If \a this is not fully defined.
6777  * \throw If \a this is not a mesh with meshDimension equal to 1.
6778  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6779  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6780  */
6781 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6782 {
6783   checkFullyDefined();
6784   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6785   if(spaceDim!=2 || mDim!=1)
6786     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!");
6787   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6788   double *bbox(ret->getPointer());
6789   const double *coords(_coords->getConstPointer());
6790   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6791   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6792     {
6793       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6794       int sz(connI[1]-connI[0]-1);
6795       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6796       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6797       INTERP_KERNEL::Edge *edge(0);
6798       for(int j=0;j<sz;j++)
6799         {
6800           int nodeId(conn[*connI+1+j]);
6801           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6802         }
6803       if(!cm.isQuadratic())
6804         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6805       else
6806         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6807       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6808       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6809     }
6810   return ret.retn();
6811 }
6812
6813 /// @cond INTERNAL
6814
6815 namespace MEDCouplingImpl
6816 {
6817   class ConnReader
6818   {
6819   public:
6820     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6821     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6822   private:
6823     const int *_conn;
6824     int _val;
6825   };
6826
6827   class ConnReader2
6828   {
6829   public:
6830     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6831     bool operator() (const int& pos) { return _conn[pos]==_val; }
6832   private:
6833     const int *_conn;
6834     int _val;
6835   };
6836 }
6837
6838 /// @endcond
6839
6840 /*!
6841  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6842  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6843  * \a this is composed in cell types.
6844  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6845  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6846  * This parameter is kept only for compatibility with other methode listed above.
6847  */
6848 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6849 {
6850   checkConnectivityFullyDefined();
6851   const int *conn=_nodal_connec->getConstPointer();
6852   const int *connI=_nodal_connec_index->getConstPointer();
6853   const int *work=connI;
6854   int nbOfCells=getNumberOfCells();
6855   std::size_t n=getAllGeoTypes().size();
6856   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6857   std::set<INTERP_KERNEL::NormalizedCellType> types;
6858   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6859     {
6860       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6861       if(types.find(typ)!=types.end())
6862         {
6863           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6864           oss << " is not contiguous !";
6865           throw INTERP_KERNEL::Exception(oss.str().c_str());
6866         }
6867       types.insert(typ);
6868       ret[3*i]=typ;
6869       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
6870       ret[3*i+1]=(int)std::distance(work,work2);
6871       work=work2;
6872     }
6873   return ret;
6874 }
6875
6876 /*!
6877  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6878  * only for types cell, type node is not managed.
6879  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6880  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6881  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6882  * If 2 or more same geometric type is in \a code and exception is thrown too.
6883  *
6884  * This method firstly checks
6885  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6886  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6887  * an exception is thrown too.
6888  * 
6889  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6890  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6891  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6892  */
6893 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6894 {
6895   if(code.empty())
6896     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6897   std::size_t sz=code.size();
6898   std::size_t n=sz/3;
6899   if(sz%3!=0)
6900     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6901   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6902   int nb=0;
6903   bool isNoPflUsed=true;
6904   for(std::size_t i=0;i<n;i++)
6905     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6906       {
6907         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6908         nb+=code[3*i+1];
6909         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6910           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6911         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6912       }
6913   if(types.size()!=n)
6914     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6915   if(isNoPflUsed)
6916     {
6917       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6918         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6919       if(types.size()==_types.size())
6920         return 0;
6921     }
6922   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6923   ret->alloc(nb,1);
6924   int *retPtr=ret->getPointer();
6925   const int *connI=_nodal_connec_index->getConstPointer();
6926   const int *conn=_nodal_connec->getConstPointer();
6927   int nbOfCells=getNumberOfCells();
6928   const int *i=connI;
6929   int kk=0;
6930   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6931     {
6932       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
6933       int offset=(int)std::distance(connI,i);
6934       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
6935       int nbOfCellsOfCurType=(int)std::distance(i,j);
6936       if(code[3*kk+2]==-1)
6937         for(int k=0;k<nbOfCellsOfCurType;k++)
6938           *retPtr++=k+offset;
6939       else
6940         {
6941           int idInIdsPerType=code[3*kk+2];
6942           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6943             {
6944               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6945               if(zePfl)
6946                 {
6947                   zePfl->checkAllocated();
6948                   if(zePfl->getNumberOfComponents()==1)
6949                     {
6950                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6951                         {
6952                           if(*k>=0 && *k<nbOfCellsOfCurType)
6953                             *retPtr=(*k)+offset;
6954                           else
6955                             {
6956                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6957                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6958                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6959                             }
6960                         }
6961                     }
6962                   else
6963                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6964                 }
6965               else
6966                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6967             }
6968           else
6969             {
6970               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6971               oss << " should be in [0," << idsPerType.size() << ") !";
6972               throw INTERP_KERNEL::Exception(oss.str().c_str());
6973             }
6974         }
6975       i=j;
6976     }
6977   return ret.retn();
6978 }
6979
6980 /*!
6981  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6982  * 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.
6983  * 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.
6984  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6985  * 
6986  * \param [in] profile
6987  * \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.
6988  * \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,
6989  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6990  * \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.
6991  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6992  * \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
6993  */
6994 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6995 {
6996   if(!profile)
6997     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6998   if(profile->getNumberOfComponents()!=1)
6999     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7000   checkConnectivityFullyDefined();
7001   const int *conn=_nodal_connec->getConstPointer();
7002   const int *connI=_nodal_connec_index->getConstPointer();
7003   int nbOfCells=getNumberOfCells();
7004   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7005   std::vector<int> typeRangeVals(1);
7006   for(const int *i=connI;i!=connI+nbOfCells;)
7007     {
7008       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7009       if(std::find(types.begin(),types.end(),curType)!=types.end())
7010         {
7011           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7012         }
7013       types.push_back(curType);
7014       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7015       typeRangeVals.push_back((int)std::distance(connI,i));
7016     }
7017   //
7018   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7019   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7020   MCAuto<DataArrayInt> tmp0=castArr;
7021   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7022   MCAuto<DataArrayInt> tmp2=castsPresent;
7023   //
7024   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7025   code.resize(3*nbOfCastsFinal);
7026   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7027   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7028   for(int i=0;i<nbOfCastsFinal;i++)
7029     {
7030       int castId=castsPresent->getIJ(i,0);
7031       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7032       idsInPflPerType2.push_back(tmp3);
7033       code[3*i]=(int)types[castId];
7034       code[3*i+1]=tmp3->getNumberOfTuples();
7035       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7036       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7037         {
7038           tmp4->copyStringInfoFrom(*profile);
7039           idsPerType2.push_back(tmp4);
7040           code[3*i+2]=(int)idsPerType2.size()-1;
7041         }
7042       else
7043         {
7044           code[3*i+2]=-1;
7045         }
7046     }
7047   std::size_t sz2=idsInPflPerType2.size();
7048   idsInPflPerType.resize(sz2);
7049   for(std::size_t i=0;i<sz2;i++)
7050     {
7051       DataArrayInt *locDa=idsInPflPerType2[i];
7052       locDa->incrRef();
7053       idsInPflPerType[i]=locDa;
7054     }
7055   std::size_t sz=idsPerType2.size();
7056   idsPerType.resize(sz);
7057   for(std::size_t i=0;i<sz;i++)
7058     {
7059       DataArrayInt *locDa=idsPerType2[i];
7060       locDa->incrRef();
7061       idsPerType[i]=locDa;
7062     }
7063 }
7064
7065 /*!
7066  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7067  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7068  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7069  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
7070  */
7071 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7072 {
7073   checkFullyDefined();
7074   nM1LevMesh->checkFullyDefined();
7075   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7076     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7077   if(_coords!=nM1LevMesh->getCoords())
7078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7079   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7080   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7081   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7082   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7083   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7084   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7085   tmp->setConnectivity(tmp0,tmp1);
7086   tmp->renumberCells(ret0->getConstPointer(),false);
7087   revDesc=tmp->getNodalConnectivity();
7088   revDescIndx=tmp->getNodalConnectivityIndex();
7089   DataArrayInt *ret=0;
7090   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7091     {
7092       int tmp2;
7093       ret->getMaxValue(tmp2);
7094       ret->decrRef();
7095       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7096       throw INTERP_KERNEL::Exception(oss.str().c_str());
7097     }
7098   nM1LevMeshIds=ret;
7099   //
7100   revDesc->incrRef();
7101   revDescIndx->incrRef();
7102   ret1->incrRef();
7103   ret0->incrRef();
7104   meshnM1Old2New=ret0;
7105   return ret1;
7106 }
7107
7108 /*!
7109  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7110  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7111  * in "Old to New" mode.
7112  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7113  *          this array using decrRef() as it is no more needed.
7114  *  \throw If the nodal connectivity of cells is not defined.
7115  */
7116 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7117 {
7118   checkConnectivityFullyDefined();
7119   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7120   renumberCells(ret->getConstPointer(),false);
7121   return ret.retn();
7122 }
7123
7124 /*!
7125  * This methods checks that cells are sorted by their types.
7126  * This method makes asumption (no check) that connectivity is correctly set before calling.
7127  */
7128 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7129 {
7130   checkFullyDefined();
7131   const int *conn=_nodal_connec->getConstPointer();
7132   const int *connI=_nodal_connec_index->getConstPointer();
7133   int nbOfCells=getNumberOfCells();
7134   std::set<INTERP_KERNEL::NormalizedCellType> types;
7135   for(const int *i=connI;i!=connI+nbOfCells;)
7136     {
7137       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7138       if(types.find(curType)!=types.end())
7139         return false;
7140       types.insert(curType);
7141       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7142     }
7143   return true;
7144 }
7145
7146 /*!
7147  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7148  * The geometric type order is specified by MED file.
7149  * 
7150  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7151  */
7152 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7153 {
7154   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7155 }
7156
7157 /*!
7158  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7159  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7160  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7161  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7162  */
7163 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7164 {
7165   checkFullyDefined();
7166   const int *conn=_nodal_connec->getConstPointer();
7167   const int *connI=_nodal_connec_index->getConstPointer();
7168   int nbOfCells=getNumberOfCells();
7169   if(nbOfCells==0)
7170     return true;
7171   int lastPos=-1;
7172   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7173   for(const int *i=connI;i!=connI+nbOfCells;)
7174     {
7175       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7176       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7177       if(isTypeExists!=orderEnd)
7178         {
7179           int pos=(int)std::distance(orderBg,isTypeExists);
7180           if(pos<=lastPos)
7181             return false;
7182           lastPos=pos;
7183           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7184         }
7185       else
7186         {
7187           if(sg.find(curType)==sg.end())
7188             {
7189               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7190               sg.insert(curType);
7191             }
7192           else
7193             return false;
7194         }
7195     }
7196   return true;
7197 }
7198
7199 /*!
7200  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7201  * 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
7202  * 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'.
7203  */
7204 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7205 {
7206   checkConnectivityFullyDefined();
7207   int nbOfCells=getNumberOfCells();
7208   const int *conn=_nodal_connec->getConstPointer();
7209   const int *connI=_nodal_connec_index->getConstPointer();
7210   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7211   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7212   tmpa->alloc(nbOfCells,1);
7213   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7214   tmpb->fillWithZero();
7215   int *tmp=tmpa->getPointer();
7216   int *tmp2=tmpb->getPointer();
7217   for(const int *i=connI;i!=connI+nbOfCells;i++)
7218     {
7219       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7220       if(where!=orderEnd)
7221         {
7222           int pos=(int)std::distance(orderBg,where);
7223           tmp2[pos]++;
7224           tmp[std::distance(connI,i)]=pos;
7225         }
7226       else
7227         {
7228           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7229           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7230           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7231           throw INTERP_KERNEL::Exception(oss.str().c_str());
7232         }
7233     }
7234   nbPerType=tmpb.retn();
7235   return tmpa.retn();
7236 }
7237
7238 /*!
7239  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7240  *
7241  * \return a new object containing the old to new correspondance.
7242  *
7243  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7244  */
7245 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7246 {
7247   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7248 }
7249
7250 /*!
7251  * 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.
7252  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7253  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7254  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7255  */
7256 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7257 {
7258   DataArrayInt *nbPerType=0;
7259   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7260   nbPerType->decrRef();
7261   return tmpa->buildPermArrPerLevel();
7262 }
7263
7264 /*!
7265  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7266  * The number of cells remains unchanged after the call of this method.
7267  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7268  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7269  *
7270  * \return the array giving the correspondance old to new.
7271  */
7272 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7273 {
7274   checkFullyDefined();
7275   computeTypes();
7276   const int *conn=_nodal_connec->getConstPointer();
7277   const int *connI=_nodal_connec_index->getConstPointer();
7278   int nbOfCells=getNumberOfCells();
7279   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7280   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7281     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7282       {
7283         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7284         types.push_back(curType);
7285         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7286       }
7287   DataArrayInt *ret=DataArrayInt::New();
7288   ret->alloc(nbOfCells,1);
7289   int *retPtr=ret->getPointer();
7290   std::fill(retPtr,retPtr+nbOfCells,-1);
7291   int newCellId=0;
7292   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7293     {
7294       for(const int *i=connI;i!=connI+nbOfCells;i++)
7295         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7296           retPtr[std::distance(connI,i)]=newCellId++;
7297     }
7298   renumberCells(retPtr,false);
7299   return ret;
7300 }
7301
7302 /*!
7303  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7304  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7305  * This method makes asumption that connectivity is correctly set before calling.
7306  */
7307 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7308 {
7309   checkConnectivityFullyDefined();
7310   const int *conn=_nodal_connec->getConstPointer();
7311   const int *connI=_nodal_connec_index->getConstPointer();
7312   int nbOfCells=getNumberOfCells();
7313   std::vector<MEDCouplingUMesh *> ret;
7314   for(const int *i=connI;i!=connI+nbOfCells;)
7315     {
7316       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7317       int beginCellId=(int)std::distance(connI,i);
7318       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7319       int endCellId=(int)std::distance(connI,i);
7320       int sz=endCellId-beginCellId;
7321       int *cells=new int[sz];
7322       for(int j=0;j<sz;j++)
7323         cells[j]=beginCellId+j;
7324       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7325       delete [] cells;
7326       ret.push_back(m);
7327     }
7328   return ret;
7329 }
7330
7331 /*!
7332  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7333  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7334  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7335  *
7336  * \return a newly allocated instance, that the caller must manage.
7337  * \throw If \a this contains more than one geometric type.
7338  * \throw If the nodal connectivity of \a this is not fully defined.
7339  * \throw If the internal data is not coherent.
7340  */
7341 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7342 {
7343   checkConnectivityFullyDefined();
7344   if(_types.size()!=1)
7345     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7346   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7347   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7348   ret->setCoords(getCoords());
7349   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7350   if(retC)
7351     {
7352       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7353       retC->setNodalConnectivity(c);
7354     }
7355   else
7356     {
7357       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7358       if(!retD)
7359         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7360       DataArrayInt *c=0,*ci=0;
7361       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7362       MCAuto<DataArrayInt> cs(c),cis(ci);
7363       retD->setNodalConnectivity(cs,cis);
7364     }
7365   return ret.retn();
7366 }
7367
7368 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7369 {
7370   checkConnectivityFullyDefined();
7371   if(_types.size()!=1)
7372     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7373   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7374   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7375   if(cm.isDynamic())
7376     {
7377       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7378       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7379       throw INTERP_KERNEL::Exception(oss.str().c_str());
7380     }
7381   int nbCells=getNumberOfCells();
7382   int typi=(int)typ;
7383   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7384   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7385   int *outPtr=connOut->getPointer();
7386   const int *conn=_nodal_connec->begin();
7387   const int *connI=_nodal_connec_index->begin();
7388   nbNodesPerCell++;
7389   for(int i=0;i<nbCells;i++,connI++)
7390     {
7391       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7392         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7393       else
7394         {
7395           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 << ") !";
7396           throw INTERP_KERNEL::Exception(oss.str().c_str());
7397         }
7398     }
7399   return connOut.retn();
7400 }
7401
7402 /*!
7403  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7404  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7405  * \param nodalConn
7406  * \param nodalConnI
7407  */
7408 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7409 {
7410   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7411   checkConnectivityFullyDefined();
7412   if(_types.size()!=1)
7413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7414   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7415   if(lgth<nbCells)
7416     throw INTERP_KERNEL::Exception(msg0);
7417   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7418   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7419   int *cp(c->getPointer()),*cip(ci->getPointer());
7420   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7421   cip[0]=0;
7422   for(int i=0;i<nbCells;i++,cip++,incip++)
7423     {
7424       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7425       int delta(stop-strt);
7426       if(delta>=1)
7427         {
7428           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7429             cp=std::copy(incp+strt,incp+stop,cp);
7430           else
7431             throw INTERP_KERNEL::Exception(msg0);
7432         }
7433       else
7434         throw INTERP_KERNEL::Exception(msg0);
7435       cip[1]=cip[0]+delta;
7436     }
7437   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7438 }
7439
7440 /*!
7441  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7442  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7443  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7444  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7445  * are not used here to avoid the build of big permutation array.
7446  *
7447  * \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
7448  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7449  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7450  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7451  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7452  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7453  * \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
7454  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7455  */
7456 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7457                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7458                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7459 {
7460   std::vector<const MEDCouplingUMesh *> ms2;
7461   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7462     if(*it)
7463       {
7464         (*it)->checkConnectivityFullyDefined();
7465         ms2.push_back(*it);
7466       }
7467   if(ms2.empty())
7468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7469   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7470   int meshDim=ms2[0]->getMeshDimension();
7471   std::vector<const MEDCouplingUMesh *> m1ssm;
7472   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7473   //
7474   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7475   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7476   int fake=0,rk=0;
7477   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7478   ret1->alloc(0,1); ret2->alloc(0,1);
7479   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7480     {
7481       if(meshDim!=(*it)->getMeshDimension())
7482         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7483       if(refCoo!=(*it)->getCoords())
7484         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7485       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7486       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7487       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7488       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7489         {
7490           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7491           m1ssmSingleAuto.push_back(singleCell);
7492           m1ssmSingle.push_back(singleCell);
7493           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7494         }
7495     }
7496   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7497   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7498   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7499   for(std::size_t i=0;i<m1ssm.size();i++)
7500     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7501   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7502   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7503   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7504   return ret0.retn();
7505 }
7506
7507 /*!
7508  * This method returns a newly created DataArrayInt instance.
7509  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7510  */
7511 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7512 {
7513   checkFullyDefined();
7514   const int *conn=_nodal_connec->getConstPointer();
7515   const int *connIndex=_nodal_connec_index->getConstPointer();
7516   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7517   for(const int *w=begin;w!=end;w++)
7518     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7519       ret->pushBackSilent(*w);
7520   return ret.retn();
7521 }
7522
7523 /*!
7524  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7525  * are in [0:getNumberOfCells())
7526  */
7527 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7528 {
7529   checkFullyDefined();
7530   const int *conn=_nodal_connec->getConstPointer();
7531   const int *connI=_nodal_connec_index->getConstPointer();
7532   int nbOfCells=getNumberOfCells();
7533   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7534   int *tmp=new int[nbOfCells];
7535   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7536     {
7537       int j=0;
7538       for(const int *i=connI;i!=connI+nbOfCells;i++)
7539         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7540           tmp[std::distance(connI,i)]=j++;
7541     }
7542   DataArrayInt *ret=DataArrayInt::New();
7543   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7544   ret->copyStringInfoFrom(*da);
7545   int *retPtr=ret->getPointer();
7546   const int *daPtr=da->getConstPointer();
7547   int nbOfElems=da->getNbOfElems();
7548   for(int k=0;k<nbOfElems;k++)
7549     retPtr[k]=tmp[daPtr[k]];
7550   delete [] tmp;
7551   return ret;
7552 }
7553
7554 /*!
7555  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7556  * This method \b works \b for mesh sorted by type.
7557  * cells whose ids is in 'idsPerGeoType' array.
7558  * This method conserves coords and name of mesh.
7559  */
7560 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7561 {
7562   std::vector<int> code=getDistributionOfTypes();
7563   std::size_t nOfTypesInThis=code.size()/3;
7564   int sz=0,szOfType=0;
7565   for(std::size_t i=0;i<nOfTypesInThis;i++)
7566     {
7567       if(code[3*i]!=type)
7568         sz+=code[3*i+1];
7569       else
7570         szOfType=code[3*i+1];
7571     }
7572   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7573     if(*work<0 || *work>=szOfType)
7574       {
7575         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7576         oss << ". It should be in [0," << szOfType << ") !";
7577         throw INTERP_KERNEL::Exception(oss.str().c_str());
7578       }
7579   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7580   int *idsPtr=idsTokeep->getPointer();
7581   int offset=0;
7582   for(std::size_t i=0;i<nOfTypesInThis;i++)
7583     {
7584       if(code[3*i]!=type)
7585         for(int j=0;j<code[3*i+1];j++)
7586           *idsPtr++=offset+j;
7587       else
7588         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7589       offset+=code[3*i+1];
7590     }
7591   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7592   ret->copyTinyInfoFrom(this);
7593   return ret.retn();
7594 }
7595
7596 /*!
7597  * This method returns a vector of size 'this->getNumberOfCells()'.
7598  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7599  */
7600 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7601 {
7602   int ncell=getNumberOfCells();
7603   std::vector<bool> ret(ncell);
7604   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7605   const int *c=getNodalConnectivity()->getConstPointer();
7606   for(int i=0;i<ncell;i++)
7607     {
7608       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7609       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7610       ret[i]=cm.isQuadratic();
7611     }
7612   return ret;
7613 }
7614
7615 /*!
7616  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7617  */
7618 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7619 {
7620   if(other->getType()!=UNSTRUCTURED)
7621     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7622   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7623   return MergeUMeshes(this,otherC);
7624 }
7625
7626 /*!
7627  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7628  * computed by averaging coordinates of cell nodes, so this method is not a right
7629  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7630  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7631  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7632  *          components. The caller is to delete this array using decrRef() as it is
7633  *          no more needed.
7634  *  \throw If the coordinates array is not set.
7635  *  \throw If the nodal connectivity of cells is not defined.
7636  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7637  */
7638 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7639 {
7640   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7641   int spaceDim=getSpaceDimension();
7642   int nbOfCells=getNumberOfCells();
7643   ret->alloc(nbOfCells,spaceDim);
7644   ret->copyStringInfoFrom(*getCoords());
7645   double *ptToFill=ret->getPointer();
7646   const int *nodal=_nodal_connec->getConstPointer();
7647   const int *nodalI=_nodal_connec_index->getConstPointer();
7648   const double *coor=_coords->getConstPointer();
7649   for(int i=0;i<nbOfCells;i++)
7650     {
7651       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7652       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7653       ptToFill+=spaceDim;
7654     }
7655   return ret.retn();
7656 }
7657
7658 /*!
7659  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7660  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7661  * 
7662  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7663  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7664  * 
7665  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7666  * \throw If \a this is not fully defined (coordinates and connectivity)
7667  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7668  */
7669 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7670 {
7671   checkFullyDefined();
7672   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7673   int spaceDim=getSpaceDimension();
7674   int nbOfCells=getNumberOfCells();
7675   int nbOfNodes=getNumberOfNodes();
7676   ret->alloc(nbOfCells,spaceDim);
7677   double *ptToFill=ret->getPointer();
7678   const int *nodal=_nodal_connec->getConstPointer();
7679   const int *nodalI=_nodal_connec_index->getConstPointer();
7680   const double *coor=_coords->getConstPointer();
7681   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7682     {
7683       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7684       std::fill(ptToFill,ptToFill+spaceDim,0.);
7685       if(type!=INTERP_KERNEL::NORM_POLYHED)
7686         {
7687           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7688             {
7689               if(*conn>=0 && *conn<nbOfNodes)
7690                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7691               else
7692                 {
7693                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7694                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7695                 }
7696             }
7697           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7698           if(nbOfNodesInCell>0)
7699             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7700           else
7701             {
7702               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7703               throw INTERP_KERNEL::Exception(oss.str().c_str());
7704             }
7705         }
7706       else
7707         {
7708           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7709           s.erase(-1);
7710           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7711             {
7712               if(*it>=0 && *it<nbOfNodes)
7713                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7714               else
7715                 {
7716                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7717                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7718                 }
7719             }
7720           if(!s.empty())
7721             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7722           else
7723             {
7724               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7725               throw INTERP_KERNEL::Exception(oss.str().c_str());
7726             }
7727         }
7728     }
7729   return ret.retn();
7730 }
7731
7732 /*!
7733  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7734  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7735  * are specified via an array of cell ids. 
7736  *  \warning Validity of the specified cell ids is not checked! 
7737  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7738  *  \param [in] begin - an array of cell ids of interest.
7739  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7740  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7741  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7742  *          caller is to delete this array using decrRef() as it is no more needed. 
7743  *  \throw If the coordinates array is not set.
7744  *  \throw If the nodal connectivity of cells is not defined.
7745  *
7746  *  \if ENABLE_EXAMPLES
7747  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7748  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7749  *  \endif
7750  */
7751 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7752 {
7753   DataArrayDouble *ret=DataArrayDouble::New();
7754   int spaceDim=getSpaceDimension();
7755   int nbOfTuple=(int)std::distance(begin,end);
7756   ret->alloc(nbOfTuple,spaceDim);
7757   double *ptToFill=ret->getPointer();
7758   double *tmp=new double[spaceDim];
7759   const int *nodal=_nodal_connec->getConstPointer();
7760   const int *nodalI=_nodal_connec_index->getConstPointer();
7761   const double *coor=_coords->getConstPointer();
7762   for(const int *w=begin;w!=end;w++)
7763     {
7764       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7765       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7766       ptToFill+=spaceDim;
7767     }
7768   delete [] tmp;
7769   return ret;
7770 }
7771
7772 /*!
7773  * 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".
7774  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7775  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7776  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7777  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7778  * 
7779  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7780  * \throw If spaceDim!=3 or meshDim!=2.
7781  * \throw If connectivity of \a this is invalid.
7782  * \throw If connectivity of a cell in \a this points to an invalid node.
7783  */
7784 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7785 {
7786   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7787   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7788   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7789     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7790   ret->alloc(nbOfCells,4);
7791   double *retPtr(ret->getPointer());
7792   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7793   const double *coor(_coords->begin());
7794   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7795     {
7796       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7797       if(nodalI[1]-nodalI[0]>=3)
7798         {
7799           for(int j=0;j<3;j++)
7800             {
7801               int nodeId(nodal[nodalI[0]+1+j]);
7802               if(nodeId>=0 && nodeId<nbOfNodes)
7803                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7804               else
7805                 {
7806                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7807                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7808                 }
7809             }
7810         }
7811       else
7812         {
7813           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7814           throw INTERP_KERNEL::Exception(oss.str().c_str());
7815         }
7816       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7817       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7818     }
7819   return ret.retn();
7820 }
7821
7822 /*!
7823  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7824  * 
7825  */
7826 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7827 {
7828   if(!da)
7829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7830   da->checkAllocated();
7831   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7832   ret->setCoords(da);
7833   int nbOfTuples=da->getNumberOfTuples();
7834   MCAuto<DataArrayInt> c=DataArrayInt::New();
7835   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7836   c->alloc(2*nbOfTuples,1);
7837   cI->alloc(nbOfTuples+1,1);
7838   int *cp=c->getPointer();
7839   int *cip=cI->getPointer();
7840   *cip++=0;
7841   for(int i=0;i<nbOfTuples;i++)
7842     {
7843       *cp++=INTERP_KERNEL::NORM_POINT1;
7844       *cp++=i;
7845       *cip++=2*(i+1);
7846     }
7847   ret->setConnectivity(c,cI,true);
7848   return ret.retn();
7849 }
7850 /*!
7851  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7852  * Cells and nodes of
7853  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7854  *  \param [in] mesh1 - the first mesh.
7855  *  \param [in] mesh2 - the second mesh.
7856  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7857  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7858  *          is no more needed.
7859  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7860  *  \throw If the coordinates array is not set in none of the meshes.
7861  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7862  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7863  */
7864 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7865 {
7866   std::vector<const MEDCouplingUMesh *> tmp(2);
7867   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7868   return MergeUMeshes(tmp);
7869 }
7870
7871 /*!
7872  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7873  * Cells and nodes of
7874  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7875  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7876  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7877  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7878  *          is no more needed.
7879  *  \throw If \a a.size() == 0.
7880  *  \throw If \a a[ *i* ] == NULL.
7881  *  \throw If the coordinates array is not set in none of the meshes.
7882  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7883  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7884  */
7885 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7886 {
7887   std::size_t sz=a.size();
7888   if(sz==0)
7889     return MergeUMeshesLL(a);
7890   for(std::size_t ii=0;ii<sz;ii++)
7891     if(!a[ii])
7892       {
7893         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7894         throw INTERP_KERNEL::Exception(oss.str().c_str());
7895       }
7896   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
7897   std::vector< const MEDCouplingUMesh * > aa(sz);
7898   int spaceDim=-3;
7899   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7900     {
7901       const MEDCouplingUMesh *cur=a[i];
7902       const DataArrayDouble *coo=cur->getCoords();
7903       if(coo)
7904         spaceDim=coo->getNumberOfComponents();
7905     }
7906   if(spaceDim==-3)
7907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7908   for(std::size_t i=0;i<sz;i++)
7909     {
7910       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7911       aa[i]=bb[i];
7912     }
7913   return MergeUMeshesLL(aa);
7914 }
7915
7916 /// @cond INTERNAL
7917
7918 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7919 {
7920   if(a.empty())
7921     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7922   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7923   int meshDim=(*it)->getMeshDimension();
7924   int nbOfCells=(*it)->getNumberOfCells();
7925   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
7926   for(;it!=a.end();it++)
7927     {
7928       if(meshDim!=(*it)->getMeshDimension())
7929         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7930       nbOfCells+=(*it)->getNumberOfCells();
7931       meshLgth+=(*it)->getNodalConnectivityArrayLen();
7932     }
7933   std::vector<const MEDCouplingPointSet *> aps(a.size());
7934   std::copy(a.begin(),a.end(),aps.begin());
7935   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
7936   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7937   ret->setCoords(pts);
7938   MCAuto<DataArrayInt> c=DataArrayInt::New();
7939   c->alloc(meshLgth,1);
7940   int *cPtr=c->getPointer();
7941   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7942   cI->alloc(nbOfCells+1,1);
7943   int *cIPtr=cI->getPointer();
7944   *cIPtr++=0;
7945   int offset=0;
7946   int offset2=0;
7947   for(it=a.begin();it!=a.end();it++)
7948     {
7949       int curNbOfCell=(*it)->getNumberOfCells();
7950       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7951       const int *curC=(*it)->_nodal_connec->getConstPointer();
7952       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7953       for(int j=0;j<curNbOfCell;j++)
7954         {
7955           const int *src=curC+curCI[j];
7956           *cPtr++=*src++;
7957           for(;src!=curC+curCI[j+1];src++,cPtr++)
7958             {
7959               if(*src!=-1)
7960                 *cPtr=*src+offset2;
7961               else
7962                 *cPtr=-1;
7963             }
7964         }
7965       offset+=curCI[curNbOfCell];
7966       offset2+=(*it)->getNumberOfNodes();
7967     }
7968   //
7969   ret->setConnectivity(c,cI,true);
7970   return ret.retn();
7971 }
7972
7973 /// @endcond
7974
7975 /*!
7976  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7977  * dimension and sharing the node coordinates array.
7978  * All cells of the first mesh precede all cells of the second mesh
7979  * within the result mesh. 
7980  *  \param [in] mesh1 - the first mesh.
7981  *  \param [in] mesh2 - the second mesh.
7982  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7983  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7984  *          is no more needed.
7985  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7986  *  \throw If the meshes do not share the node coordinates array.
7987  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7988  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7989  */
7990 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7991 {
7992   std::vector<const MEDCouplingUMesh *> tmp(2);
7993   tmp[0]=mesh1; tmp[1]=mesh2;
7994   return MergeUMeshesOnSameCoords(tmp);
7995 }
7996
7997 /*!
7998  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7999  * dimension and sharing the node coordinates array.
8000  * All cells of the *i*-th mesh precede all cells of the
8001  * (*i*+1)-th mesh within the result mesh.
8002  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8003  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8004  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8005  *          is no more needed.
8006  *  \throw If \a a.size() == 0.
8007  *  \throw If \a a[ *i* ] == NULL.
8008  *  \throw If the meshes do not share the node coordinates array.
8009  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8010  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8011  */
8012 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8013 {
8014   if(meshes.empty())
8015     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8016   for(std::size_t ii=0;ii<meshes.size();ii++)
8017     if(!meshes[ii])
8018       {
8019         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8020         throw INTERP_KERNEL::Exception(oss.str().c_str());
8021       }
8022   const DataArrayDouble *coords=meshes.front()->getCoords();
8023   int meshDim=meshes.front()->getMeshDimension();
8024   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8025   int meshLgth=0;
8026   int meshIndexLgth=0;
8027   for(;iter!=meshes.end();iter++)
8028     {
8029       if(coords!=(*iter)->getCoords())
8030         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8031       if(meshDim!=(*iter)->getMeshDimension())
8032         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8033       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8034       meshIndexLgth+=(*iter)->getNumberOfCells();
8035     }
8036   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8037   nodal->alloc(meshLgth,1);
8038   int *nodalPtr=nodal->getPointer();
8039   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8040   nodalIndex->alloc(meshIndexLgth+1,1);
8041   int *nodalIndexPtr=nodalIndex->getPointer();
8042   int offset=0;
8043   for(iter=meshes.begin();iter!=meshes.end();iter++)
8044     {
8045       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8046       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8047       int nbOfCells=(*iter)->getNumberOfCells();
8048       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8049       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8050       if(iter!=meshes.begin())
8051         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8052       else
8053         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8054       offset+=meshLgth2;
8055     }
8056   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8057   ret->setName("merge");
8058   ret->setMeshDimension(meshDim);
8059   ret->setConnectivity(nodal,nodalIndex,true);
8060   ret->setCoords(coords);
8061   return ret;
8062 }
8063
8064 /*!
8065  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8066  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8067  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8068  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8069  * New" mode are returned for each input mesh.
8070  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8071  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8072  *          valid values [0,1,2], see zipConnectivityTraducer().
8073  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8074  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8075  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8076  *          no more needed.
8077  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8078  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8079  *          is no more needed.
8080  *  \throw If \a meshes.size() == 0.
8081  *  \throw If \a meshes[ *i* ] == NULL.
8082  *  \throw If the meshes do not share the node coordinates array.
8083  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8084  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8085  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8086  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8087  */
8088 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8089 {
8090   //All checks are delegated to MergeUMeshesOnSameCoords
8091   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8092   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8093   corr.resize(meshes.size());
8094   std::size_t nbOfMeshes=meshes.size();
8095   int offset=0;
8096   const int *o2nPtr=o2n->getConstPointer();
8097   for(std::size_t i=0;i<nbOfMeshes;i++)
8098     {
8099       DataArrayInt *tmp=DataArrayInt::New();
8100       int curNbOfCells=meshes[i]->getNumberOfCells();
8101       tmp->alloc(curNbOfCells,1);
8102       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8103       offset+=curNbOfCells;
8104       tmp->setName(meshes[i]->getName());
8105       corr[i]=tmp;
8106     }
8107   return ret.retn();
8108 }
8109
8110 /*!
8111  * Makes all given meshes share the nodal connectivity array. The common connectivity
8112  * array is created by concatenating the connectivity arrays of all given meshes. All
8113  * the given meshes must be of the same space dimension but dimension of cells **can
8114  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8115  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8116  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8117  *  \param [in,out] meshes - a vector of meshes to update.
8118  *  \throw If any of \a meshes is NULL.
8119  *  \throw If the coordinates array is not set in any of \a meshes.
8120  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8121  *  \throw If \a meshes are of different space dimension.
8122  */
8123 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8124 {
8125   std::size_t sz=meshes.size();
8126   if(sz==0 || sz==1)
8127     return;
8128   std::vector< const DataArrayDouble * > coords(meshes.size());
8129   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8130   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8131     {
8132       if((*it))
8133         {
8134           (*it)->checkConnectivityFullyDefined();
8135           const DataArrayDouble *coo=(*it)->getCoords();
8136           if(coo)
8137             *it2=coo;
8138           else
8139             {
8140               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8141               oss << " has no coordinate array defined !";
8142               throw INTERP_KERNEL::Exception(oss.str().c_str());
8143             }
8144         }
8145       else
8146         {
8147           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8148           oss << " is null !";
8149           throw INTERP_KERNEL::Exception(oss.str().c_str());
8150         }
8151     }
8152   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8153   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8154   int offset=(*it)->getNumberOfNodes();
8155   (*it++)->setCoords(res);
8156   for(;it!=meshes.end();it++)
8157     {
8158       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8159       (*it)->setCoords(res);
8160       (*it)->shiftNodeNumbersInConn(offset);
8161       offset+=oldNumberOfNodes;
8162     }
8163 }
8164
8165 /*!
8166  * Merges nodes coincident with a given precision within all given meshes that share
8167  * the nodal connectivity array. The given meshes **can be of different** mesh
8168  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8169  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8170  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8171  *  \param [in,out] meshes - a vector of meshes to update.
8172  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8173  *  \throw If any of \a meshes is NULL.
8174  *  \throw If the \a meshes do not share the same node coordinates array.
8175  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8176  */
8177 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8178 {
8179   if(meshes.empty())
8180     return ;
8181   std::set<const DataArrayDouble *> s;
8182   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8183     {
8184       if(*it)
8185         s.insert((*it)->getCoords());
8186       else
8187         {
8188           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 !";
8189           throw INTERP_KERNEL::Exception(oss.str().c_str());
8190         }
8191     }
8192   if(s.size()!=1)
8193     {
8194       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 !";
8195       throw INTERP_KERNEL::Exception(oss.str().c_str());
8196     }
8197   const DataArrayDouble *coo=*(s.begin());
8198   if(!coo)
8199     return;
8200   //
8201   DataArrayInt *comm,*commI;
8202   coo->findCommonTuples(eps,-1,comm,commI);
8203   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8204   int oldNbOfNodes=coo->getNumberOfTuples();
8205   int newNbOfNodes;
8206   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8207   if(oldNbOfNodes==newNbOfNodes)
8208     return ;
8209   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8210   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8211     {
8212       (*it)->renumberNodesInConn(o2n->getConstPointer());
8213       (*it)->setCoords(newCoords);
8214     } 
8215 }
8216
8217 /*!
8218  * 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.
8219  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8220  * \param isQuad specifies the policy of connectivity.
8221  * @ret in/out parameter in which the result will be append
8222  */
8223 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8224 {
8225   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8226   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8227   ret.push_back(cm.getExtrudedType());
8228   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8229   switch(flatType)
8230   {
8231     case INTERP_KERNEL::NORM_POINT1:
8232       {
8233         ret.push_back(connBg[1]);
8234         ret.push_back(connBg[1]+nbOfNodesPerLev);
8235         break;
8236       }
8237     case INTERP_KERNEL::NORM_SEG2:
8238       {
8239         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8240         ret.insert(ret.end(),conn,conn+4);
8241         break;
8242       }
8243     case INTERP_KERNEL::NORM_SEG3:
8244       {
8245         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8246         ret.insert(ret.end(),conn,conn+8);
8247         break;
8248       }
8249     case INTERP_KERNEL::NORM_QUAD4:
8250       {
8251         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8252         ret.insert(ret.end(),conn,conn+8);
8253         break;
8254       }
8255     case INTERP_KERNEL::NORM_TRI3:
8256       {
8257         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8258         ret.insert(ret.end(),conn,conn+6);
8259         break;
8260       }
8261     case INTERP_KERNEL::NORM_TRI6:
8262       {
8263         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,
8264           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8265         ret.insert(ret.end(),conn,conn+15);
8266         break;
8267       }
8268     case INTERP_KERNEL::NORM_QUAD8:
8269       {
8270         int conn[20]={
8271           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8272           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8273           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8274         };
8275         ret.insert(ret.end(),conn,conn+20);
8276         break;
8277       }
8278     case INTERP_KERNEL::NORM_POLYGON:
8279       {
8280         std::back_insert_iterator< std::vector<int> > ii(ret);
8281         std::copy(connBg+1,connEnd,ii);
8282         *ii++=-1;
8283         std::reverse_iterator<const int *> rConnBg(connEnd);
8284         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8285         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8286         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8287         for(std::size_t i=0;i<nbOfRadFaces;i++)
8288           {
8289             *ii++=-1;
8290             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8291             std::copy(conn,conn+4,ii);
8292           }
8293         break;
8294       }
8295     default:
8296       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8297   }
8298 }
8299
8300 /*!
8301  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8302  */
8303 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8304 {
8305   std::size_t i, ip1;
8306   double v[3]={0.,0.,0.};
8307   std::size_t sz=std::distance(begin,end);
8308   if(isQuadratic)
8309     sz/=2;
8310   for(i=0;i<sz;i++)
8311     {
8312       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];
8313       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8314       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8315     }
8316   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8317
8318   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8319   // SEG3 forming a circle):
8320   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8321     {
8322       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8323       for(std::size_t j=0;j<sz;j++)
8324         {
8325           if (j%2)  // current point i is quadratic, next point i+1 is standard
8326             {
8327               i = sz+j;
8328               ip1 = (j+1)%sz; // ip1 = "i+1"
8329             }
8330           else      // current point i is standard, next point i+1 is quadratic
8331             {
8332               i = j;
8333               ip1 = j+sz;
8334             }
8335           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8336           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8337           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8338         }
8339       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8340     }
8341   return (ret>0.);
8342 }
8343
8344 /*!
8345  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8346  */
8347 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8348 {
8349   std::vector<std::pair<int,int> > edges;
8350   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8351   const int *bgFace=begin;
8352   for(std::size_t i=0;i<nbOfFaces;i++)
8353     {
8354       const int *endFace=std::find(bgFace+1,end,-1);
8355       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8356       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8357         {
8358           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8359           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8360             return false;
8361           edges.push_back(p1);
8362         }
8363       bgFace=endFace+1;
8364     }
8365   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8366 }
8367
8368 /*!
8369  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8370  */
8371 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8372 {
8373   double vec0[3],vec1[3];
8374   std::size_t sz=std::distance(begin,end);
8375   if(sz%2!=0)
8376     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8377   int nbOfNodes=(int)sz/2;
8378   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8379   const double *pt0=coords+3*begin[0];
8380   const double *pt1=coords+3*begin[nbOfNodes];
8381   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8382   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8383 }
8384
8385 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8386 {
8387   std::size_t sz=std::distance(begin,end);
8388   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8389   std::size_t nbOfNodes(sz/2);
8390   std::copy(begin,end,(int *)tmp);
8391   for(std::size_t j=1;j<nbOfNodes;j++)
8392     {
8393       begin[j]=tmp[nbOfNodes-j];
8394       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8395     }
8396 }
8397
8398 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8399 {
8400   std::size_t sz=std::distance(begin,end);
8401   if(sz!=4)
8402     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8403   double vec0[3],vec1[3];
8404   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8405   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]; 
8406   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;
8407 }
8408
8409 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8410 {
8411   std::size_t sz=std::distance(begin,end);
8412   if(sz!=5)
8413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8414   double vec0[3];
8415   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8416   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8417   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8418 }
8419
8420 /*!
8421  * 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 ) 
8422  * 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
8423  * a 2D space.
8424  *
8425  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8426  * \param [in] coords the coordinates with nb of components exactly equal to 3
8427  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8428  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8429  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8430  */
8431 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8432 {
8433   int nbFaces=std::count(begin+1,end,-1)+1;
8434   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8435   double *vPtr=v->getPointer();
8436   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8437   double *pPtr=p->getPointer();
8438   const int *stFaceConn=begin+1;
8439   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8440     {
8441       const int *endFaceConn=std::find(stFaceConn,end,-1);
8442       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8443       stFaceConn=endFaceConn+1;
8444     }
8445   pPtr=p->getPointer(); vPtr=v->getPointer();
8446   DataArrayInt *comm1=0,*commI1=0;
8447   v->findCommonTuples(eps,-1,comm1,commI1);
8448   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8449   const int *comm1Ptr=comm1->getConstPointer();
8450   const int *commI1Ptr=commI1->getConstPointer();
8451   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8452   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8453   //
8454   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8455   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8456   mm->finishInsertingCells();
8457   //
8458   for(int i=0;i<nbOfGrps1;i++)
8459     {
8460       int vecId=comm1Ptr[commI1Ptr[i]];
8461       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8462       DataArrayInt *comm2=0,*commI2=0;
8463       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8464       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8465       const int *comm2Ptr=comm2->getConstPointer();
8466       const int *commI2Ptr=commI2->getConstPointer();
8467       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8468       for(int j=0;j<nbOfGrps2;j++)
8469         {
8470           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8471             {
8472               res->insertAtTheEnd(begin,end);
8473               res->pushBackSilent(-1);
8474             }
8475           else
8476             {
8477               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8478               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8479               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8480               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8481               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8482               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8483               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8484               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8485               const int *idsNodePtr=idsNode->getConstPointer();
8486               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];
8487               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8488               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8489               if(std::abs(norm)>eps)
8490                 {
8491                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8492                   mm3->rotate(center,vec,angle);
8493                 }
8494               mm3->changeSpaceDimension(2);
8495               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8496               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8497               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8498               int nbOfCells=mm4->getNumberOfCells();
8499               for(int k=0;k<nbOfCells;k++)
8500                 {
8501                   int l=0;
8502                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8503                     res->pushBackSilent(idsNodePtr[*work]);
8504                   res->pushBackSilent(-1);
8505                 }
8506             }
8507         }
8508     }
8509   res->popBackSilent();
8510 }
8511
8512 /*!
8513  * 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
8514  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8515  * 
8516  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8517  * \param [in] coords coordinates expected to have 3 components.
8518  * \param [in] begin start of the nodal connectivity of the face.
8519  * \param [in] end end of the nodal connectivity (excluded) of the face.
8520  * \param [out] v the normalized vector of size 3
8521  * \param [out] p the pos of plane
8522  */
8523 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8524 {
8525   std::size_t nbPoints=std::distance(begin,end);
8526   if(nbPoints<3)
8527     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8528   double vec[3]={0.,0.,0.};
8529   std::size_t j=0;
8530   bool refFound=false;
8531   for(;j<nbPoints-1 && !refFound;j++)
8532     {
8533       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8534       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8535       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8536       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8537       if(norm>eps)
8538         {
8539           refFound=true;
8540           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8541         }
8542     }
8543   for(std::size_t i=j;i<nbPoints-1;i++)
8544     {
8545       double curVec[3];
8546       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8547       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8548       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8549       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8550       if(norm<eps)
8551         continue;
8552       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8553       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];
8554       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8555       if(norm>eps)
8556         {
8557           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8558           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8559           return ;
8560         }
8561     }
8562   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8563 }
8564
8565 /*!
8566  * This method tries to obtain a well oriented polyhedron.
8567  * If the algorithm fails, an exception will be thrown.
8568  */
8569 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8570 {
8571   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8572   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8573   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8574   isPerm[0]=true;
8575   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8576   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8577   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8578   //
8579   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8580     {
8581       bgFace=begin;
8582       std::size_t smthChanged=0;
8583       for(std::size_t i=0;i<nbOfFaces;i++)
8584         {
8585           endFace=std::find(bgFace+1,end,-1);
8586           nbOfEdgesInFace=std::distance(bgFace,endFace);
8587           if(!isPerm[i])
8588             {
8589               bool b;
8590               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8591                 {
8592                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8593                   std::pair<int,int> p2(p1.second,p1.first);
8594                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8595                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8596                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8597                 }
8598               if(isPerm[i])
8599                 { 
8600                   if(!b)
8601                     std::reverse(bgFace+1,endFace);
8602                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8603                     {
8604                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8605                       std::pair<int,int> p2(p1.second,p1.first);
8606                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8607                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8608                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8609                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8610                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8611                       if(it!=edgesOK.end())
8612                         {
8613                           edgesOK.erase(it);
8614                           edgesFinished.push_back(p1);
8615                         }
8616                       else
8617                         edgesOK.push_back(p1);
8618                     }
8619                 }
8620             }
8621           bgFace=endFace+1;
8622         }
8623       if(smthChanged==0)
8624         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8625     }
8626   if(!edgesOK.empty())
8627     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8628   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8629     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8630       bgFace=begin;
8631       for(std::size_t i=0;i<nbOfFaces;i++)
8632         {
8633           endFace=std::find(bgFace+1,end,-1);
8634           std::reverse(bgFace+1,endFace);
8635           bgFace=endFace+1;
8636         }
8637     }
8638 }
8639
8640 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8641 {
8642   int nbOfNodesExpected(skin->getNumberOfNodes());
8643   const int *n2oPtr(n2o->getConstPointer());
8644   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8645   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8646   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8647   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8648   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8649   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8650   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8651   if(nbOfNodesExpected<1)
8652     return ret.retn();
8653   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8654   *work++=n2oPtr[prevNode];
8655   for(int i=1;i<nbOfNodesExpected;i++)
8656     {
8657       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8658         {
8659           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8660           conn.erase(prevNode);
8661           if(conn.size()==1)
8662             {
8663               int curNode(*(conn.begin()));
8664               *work++=n2oPtr[curNode];
8665               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8666               shar.erase(prevCell);
8667               if(shar.size()==1)
8668                 {
8669                   prevCell=*(shar.begin());
8670                   prevNode=curNode;
8671                 }
8672               else
8673                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8674             }
8675           else
8676             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8677         }
8678       else
8679         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8680     }
8681   return ret.retn();
8682 }
8683
8684 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8685 {
8686   int nbOfNodesExpected(skin->getNumberOfNodes());
8687   int nbOfTurn(nbOfNodesExpected/2);
8688   const int *n2oPtr(n2o->getConstPointer());
8689   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8690   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8691   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8692   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8693   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8694   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8695   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8696   if(nbOfNodesExpected<1)
8697     return ret.retn();
8698   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8699   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8700   for(int i=1;i<nbOfTurn;i++)
8701     {
8702       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8703         {
8704           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8705           conn.erase(prevNode);
8706           if(conn.size()==1)
8707             {
8708               int curNode(*(conn.begin()));
8709               *work=n2oPtr[curNode];
8710               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8711               shar.erase(prevCell);
8712               if(shar.size()==1)
8713                 {
8714                   int curCell(*(shar.begin()));
8715                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8716                   prevCell=curCell;
8717                   prevNode=curNode;
8718                   work++;
8719                 }
8720               else
8721                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8722             }
8723           else
8724             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8725         }
8726       else
8727         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8728     }
8729   return ret.retn();
8730 }
8731
8732 /*!
8733  * This method makes the assumption spacedimension == meshdimension == 2.
8734  * This method works only for linear cells.
8735  * 
8736  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8737  */
8738 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8739 {
8740   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8742   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8743   int oldNbOfNodes(skin->getNumberOfNodes());
8744   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8745   int nbOfNodesExpected(skin->getNumberOfNodes());
8746   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8747   int nbCells(skin->getNumberOfCells());
8748   if(nbCells==nbOfNodesExpected)
8749     return buildUnionOf2DMeshLinear(skin,n2o);
8750   else if(2*nbCells==nbOfNodesExpected)
8751     return buildUnionOf2DMeshQuadratic(skin,n2o);
8752   else
8753     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8754 }
8755
8756 /*!
8757  * This method makes the assumption spacedimension == meshdimension == 3.
8758  * This method works only for linear cells.
8759  * 
8760  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8761  */
8762 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8763 {
8764   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8765     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8766   MCAuto<MEDCouplingUMesh> m=computeSkin();
8767   const int *conn=m->getNodalConnectivity()->getConstPointer();
8768   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8769   int nbOfCells=m->getNumberOfCells();
8770   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8771   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8772   if(nbOfCells<1)
8773     return ret.retn();
8774   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8775   for(int i=1;i<nbOfCells;i++)
8776     {
8777       *work++=-1;
8778       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8779     }
8780   return ret.retn();
8781 }
8782
8783 /*!
8784  * \brief Creates a graph of cell neighbors
8785  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8786  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8787  *  For example
8788  *  - index:  0 3 5 6 6
8789  *  - value:  1 2 3 2 3 3
8790  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8791  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8792  */
8793 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8794 {
8795   checkConnectivityFullyDefined();
8796
8797   int meshDim = this->getMeshDimension();
8798   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8799   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8800   this->getReverseNodalConnectivity(revConn,indexr);
8801   const int* indexr_ptr=indexr->getConstPointer();
8802   const int* revConn_ptr=revConn->getConstPointer();
8803
8804   const MEDCoupling::DataArrayInt* index;
8805   const MEDCoupling::DataArrayInt* conn;
8806   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8807   index=this->getNodalConnectivityIndex();
8808   int nbCells=this->getNumberOfCells();
8809   const int* index_ptr=index->getConstPointer();
8810   const int* conn_ptr=conn->getConstPointer();
8811
8812   //creating graph arcs (cell to cell relations)
8813   //arcs are stored in terms of (index,value) notation
8814   // 0 3 5 6 6
8815   // 1 2 3 2 3 3
8816   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8817   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8818
8819   //warning here one node have less than or equal effective number of cell with it
8820   //but cell could have more than effective nodes
8821   //because other equals nodes in other domain (with other global inode)
8822   std::vector <int> cell2cell_index(nbCells+1,0);
8823   std::vector <int> cell2cell;
8824   cell2cell.reserve(3*nbCells);
8825
8826   for (int icell=0; icell<nbCells;icell++)
8827     {
8828       std::map<int,int > counter;
8829       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8830         {
8831           int inode=conn_ptr[iconn];
8832           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8833             {
8834               int icell2=revConn_ptr[iconnr];
8835               std::map<int,int>::iterator iter=counter.find(icell2);
8836               if (iter!=counter.end()) (iter->second)++;
8837               else counter.insert(std::make_pair(icell2,1));
8838             }
8839         }
8840       for (std::map<int,int>::const_iterator iter=counter.begin();
8841            iter!=counter.end(); iter++)
8842         if (iter->second >= meshDim)
8843           {
8844             cell2cell_index[icell+1]++;
8845             cell2cell.push_back(iter->first);
8846           }
8847     }
8848   indexr->decrRef();
8849   revConn->decrRef();
8850   cell2cell_index[0]=0;
8851   for (int icell=0; icell<nbCells;icell++)
8852     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8853
8854   //filling up index and value to create skylinearray structure
8855   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8856   return array;
8857 }
8858
8859 /*!
8860  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8861  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8862  */
8863 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8864 {
8865   double *w=zipFrmt;
8866   if(spaceDim==3)
8867     for(int i=0;i<nbOfNodesInCell;i++)
8868       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8869   else if(spaceDim==2)
8870     {
8871       for(int i=0;i<nbOfNodesInCell;i++)
8872         {
8873           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8874           *w++=0.;
8875         }
8876     }
8877   else
8878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8879 }
8880
8881 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8882 {
8883   int nbOfCells=getNumberOfCells();
8884   if(nbOfCells<=0)
8885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8886   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};
8887   ofs << "  <" << getVTKDataSetType() << ">\n";
8888   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8889   ofs << "      <PointData>\n" << pointData << std::endl;
8890   ofs << "      </PointData>\n";
8891   ofs << "      <CellData>\n" << cellData << std::endl;
8892   ofs << "      </CellData>\n";
8893   ofs << "      <Points>\n";
8894   if(getSpaceDimension()==3)
8895     _coords->writeVTK(ofs,8,"Points",byteData);
8896   else
8897     {
8898       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8899       coo->writeVTK(ofs,8,"Points",byteData);
8900     }
8901   ofs << "      </Points>\n";
8902   ofs << "      <Cells>\n";
8903   const int *cPtr=_nodal_connec->getConstPointer();
8904   const int *cIPtr=_nodal_connec_index->getConstPointer();
8905   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8906   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8907   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8908   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8909   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8910   int szFaceOffsets=0,szConn=0;
8911   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8912     {
8913       *w2=cPtr[cIPtr[i]];
8914       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8915         {
8916           *w1=-1;
8917           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8918           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8919         }
8920       else
8921         {
8922           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8923           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8924           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8925           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8926           w4=std::copy(c.begin(),c.end(),w4);
8927         }
8928     }
8929   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8930   types->writeVTK(ofs,8,"UInt8","types",byteData);
8931   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8932   if(szFaceOffsets!=0)
8933     {//presence of Polyhedra
8934       connectivity->reAlloc(szConn);
8935       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8936       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8937       w1=faces->getPointer();
8938       for(int i=0;i<nbOfCells;i++)
8939         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8940           {
8941             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8942             *w1++=nbFaces;
8943             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8944             for(int j=0;j<nbFaces;j++)
8945               {
8946                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8947                 *w1++=(int)std::distance(w6,w5);
8948                 w1=std::copy(w6,w5,w1);
8949                 w6=w5+1;
8950               }
8951           }
8952       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8953     }
8954   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8955   ofs << "      </Cells>\n";
8956   ofs << "    </Piece>\n";
8957   ofs << "  </" << getVTKDataSetType() << ">\n";
8958 }
8959
8960 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8961 {
8962   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8963   if(_mesh_dim==-2)
8964     { stream << " Not set !"; return ; }
8965   stream << " Mesh dimension : " << _mesh_dim << ".";
8966   if(_mesh_dim==-1)
8967     return ;
8968   if(!_coords)
8969     { stream << " No coordinates set !"; return ; }
8970   if(!_coords->isAllocated())
8971     { stream << " Coordinates set but not allocated !"; return ; }
8972   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8973   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8974   if(!_nodal_connec_index)
8975     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8976   if(!_nodal_connec_index->isAllocated())
8977     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8978   int lgth=_nodal_connec_index->getNumberOfTuples();
8979   int cpt=_nodal_connec_index->getNumberOfComponents();
8980   if(cpt!=1 || lgth<1)
8981     return ;
8982   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8983 }
8984
8985 std::string MEDCouplingUMesh::getVTKDataSetType() const
8986 {
8987   return std::string("UnstructuredGrid");
8988 }
8989
8990 std::string MEDCouplingUMesh::getVTKFileExtension() const
8991 {
8992   return std::string("vtu");
8993 }
8994
8995 /*!
8996  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8997  * returns a result mesh constituted by polygons.
8998  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8999  * all nodes from m2.
9000  * The meshes should be in 2D space. In
9001  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9002  * meshes.
9003  *  \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
9004  *                      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)
9005  *  \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
9006  *                      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)
9007  *  \param [in] eps - precision used to detect coincident mesh entities.
9008  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9009  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9010  *         this array using decrRef() as it is no more needed.
9011  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9012  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9013  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9014  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9015  *         it is no more needed.  
9016  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9017  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9018  *         is no more needed.  
9019  *  \throw If the coordinates array is not set in any of the meshes.
9020  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9021  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9022  *
9023  *  \sa conformize2D, mergeNodes
9024  */
9025 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9026                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9027 {
9028   if(!m1 || !m2)
9029     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9030   m1->checkFullyDefined();
9031   m2->checkFullyDefined();
9032   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9033     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9034
9035   // Step 1: compute all edge intersections (new nodes)
9036   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9037   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9038   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9039   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9040   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9041                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9042                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9043   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9044   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9045   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9046
9047   // Step 2: re-order newly created nodes according to the ordering found in m2
9048   std::vector< std::vector<int> > intersectEdge2;
9049   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9050   subDiv2.clear(); dd5=0; dd6=0;
9051
9052   // Step 3:
9053   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9054   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9055   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9056                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9057
9058   // Step 4: Prepare final result:
9059   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9060   addCooDa->alloc((int)(addCoo.size())/2,2);
9061   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9062   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9063   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9064   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9065   std::vector<const DataArrayDouble *> coordss(4);
9066   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9067   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9068   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9069   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9070   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9071   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9072   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9073   ret->setConnectivity(conn,connI,true);
9074   ret->setCoords(coo);
9075   cellNb1=c1.retn(); cellNb2=c2.retn();
9076   return ret.retn();
9077 }
9078
9079 /// @cond INTERNAL
9080
9081 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9082 {
9083   if(candidates.empty())
9084     return false;
9085   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9086     {
9087       const std::vector<int>& pool(intersectEdge1[*it]);
9088       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9089       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9090         {
9091           retVal=*it+1;
9092           return true;
9093         }
9094       tmp[0]=stop; tmp[1]=start;
9095       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9096         {
9097           retVal=-*it-1;
9098           return true;
9099         }
9100     }
9101   return false;
9102 }
9103
9104 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,
9105                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9106 {
9107   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9108   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9109   int nCells(mesh1D->getNumberOfCells());
9110   if(nCells!=(int)intersectEdge2.size())
9111     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9112   const DataArrayDouble *coo2(mesh1D->getCoords());
9113   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9114   const double *coo2Ptr(coo2->begin());
9115   int offset1(coords1->getNumberOfTuples());
9116   int offset2(offset1+coo2->getNumberOfTuples());
9117   int offset3(offset2+addCoo.size()/2);
9118   std::vector<double> addCooQuad;
9119   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9120   int tmp[4],cicnt(0),kk(0);
9121   for(int i=0;i<nCells;i++)
9122     {
9123       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9124       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9125       const std::vector<int>& subEdges(intersectEdge2[i]);
9126       int nbSubEdge(subEdges.size()/2);
9127       for(int j=0;j<nbSubEdge;j++,kk++)
9128         {
9129           MCAuto<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));
9130           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9131           INTERP_KERNEL::Edge *e2Ptr(e2);
9132           std::map<int,int>::const_iterator itm;
9133           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9134             {
9135               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9136               itm=mergedNodes.find(subEdges[2*j]);
9137               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9138               itm=mergedNodes.find(subEdges[2*j+1]);
9139               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9140               tmp[3]=offset3+(int)addCooQuad.size()/2;
9141               double tmp2[2];
9142               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9143               cicnt+=4;
9144               cOut->insertAtTheEnd(tmp,tmp+4);
9145               ciOut->pushBackSilent(cicnt);
9146             }
9147           else
9148             {
9149               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9150               itm=mergedNodes.find(subEdges[2*j]);
9151               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9152               itm=mergedNodes.find(subEdges[2*j+1]);
9153               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9154               cicnt+=3;
9155               cOut->insertAtTheEnd(tmp,tmp+3);
9156               ciOut->pushBackSilent(cicnt);
9157             }
9158           int tmp00;
9159           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9160             {
9161               idsInRetColinear->pushBackSilent(kk);
9162               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9163             }
9164         }
9165       e->decrRef();
9166     }
9167   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9168   ret->setConnectivity(cOut,ciOut,true);
9169   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9170   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9171   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9172   std::vector<const DataArrayDouble *> coordss(4);
9173   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9174   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9175   ret->setCoords(arr);
9176   return ret.retn();
9177 }
9178
9179 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9180 {
9181   std::vector<int> allEdges;
9182   for(const int *it2(descBg);it2!=descEnd;it2++)
9183     {
9184       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9185       if(*it2>0)
9186         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9187       else
9188         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9189     }
9190   std::size_t nb(allEdges.size());
9191   if(nb%2!=0)
9192     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9193   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9194   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9195   ret->setCoords(coords);
9196   ret->allocateCells(1);
9197   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9198   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9199     connOut[kk]=allEdges[2*kk];
9200   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9201   return ret.retn();
9202 }
9203
9204 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9205 {
9206   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9207   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9208   std::size_t ii(0);
9209   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9210   if(sz!=std::distance(descBg,descEnd))
9211     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9212   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9213   std::vector<int> allEdges,centers;
9214   const double *coordsPtr(coords->begin());
9215   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9216   int offset(coords->getNumberOfTuples());
9217   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9218     {
9219       INTERP_KERNEL::NormalizedCellType typeOfSon;
9220       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9221       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9222       if(*it2>0)
9223         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9224       else
9225         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9226       if(edge1.size()==2)
9227         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9228       else
9229         {//the current edge has been subsplit -> create corresponding centers.
9230           std::size_t nbOfCentersToAppend(edge1.size()/2);
9231           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9232           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9233           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9234           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9235             {
9236               double tmpp[2];
9237               const double *aa(coordsPtr+2*(*it3++));
9238               const double *bb(coordsPtr+2*(*it3++));
9239               ee->getMiddleOfPoints(aa,bb,tmpp);
9240               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9241               centers.push_back(offset+k);
9242             }
9243         }
9244     }
9245   std::size_t nb(allEdges.size());
9246   if(nb%2!=0)
9247     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9248   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9249   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9250   if(addCoo->empty())
9251     ret->setCoords(coords);
9252   else
9253     {
9254       addCoo->rearrange(2);
9255       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9256       ret->setCoords(addCoo);
9257     }
9258   ret->allocateCells(1);
9259   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9260   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9261     connOut[kk]=allEdges[2*kk];
9262   connOut.insert(connOut.end(),centers.begin(),centers.end());
9263   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9264   return ret.retn();
9265 }
9266
9267 /*!
9268  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9269  * of those edges.
9270  *
9271  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9272  */
9273 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9274 {
9275   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9276   if(!cm.isQuadratic())
9277     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9278   else
9279     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9280 }
9281
9282 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9283 {
9284   bool isQuad(false);
9285   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9286     {
9287       const INTERP_KERNEL::Edge *ee(*it);
9288       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9289         isQuad=true;
9290     }
9291   if(!isQuad)
9292     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9293   else
9294     {
9295       const double *coo(mesh2D->getCoords()->begin());
9296       std::size_t sz(conn.size());
9297       std::vector<double> addCoo;
9298       std::vector<int> conn2(conn);
9299       int offset(mesh2D->getNumberOfNodes());
9300       for(std::size_t i=0;i<sz;i++)
9301         {
9302           double tmp[2];
9303           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9304           addCoo.insert(addCoo.end(),tmp,tmp+2);
9305           conn2.push_back(offset+(int)i);
9306         }
9307       mesh2D->getCoords()->rearrange(1);
9308       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9309       mesh2D->getCoords()->rearrange(2);
9310       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9311     }
9312 }
9313
9314 /*!
9315  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9316  *
9317  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9318  * a set of edges defined in \a splitMesh1D.
9319  */
9320 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9321                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9322 {
9323   std::size_t nb(edge1Bis.size()/2);
9324   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9325   int iEnd(splitMesh1D->getNumberOfCells());
9326   if(iEnd==0)
9327     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9328   std::size_t ii,jj;
9329   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9330   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9331   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9332   //
9333   if(jj==nb)
9334     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9335       out0.resize(1); out1.resize(1);
9336       std::vector<int>& connOut(out0[0]);
9337       connOut.resize(nbOfEdgesOf2DCellSplit);
9338       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9339       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9340       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9341         {
9342           connOut[kk]=edge1Bis[2*kk];
9343           edgesPtr[kk]=edge1BisPtr[2*kk];
9344         }
9345     }
9346   else
9347     {
9348       // [i,iEnd[ contains the
9349       out0.resize(2); out1.resize(2);
9350       std::vector<int>& connOutLeft(out0[0]);
9351       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9352       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9353       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9354       for(std::size_t k=ii;k<jj+1;k++)
9355         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9356       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9357       for(int ik=0;ik<iEnd;ik++)
9358         {
9359           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9360           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9361           ees[ik]=ee;
9362         }
9363       for(int ik=iEnd-1;ik>=0;ik--)
9364         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9365       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9366         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9367       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9368       for(int ik=0;ik<iEnd;ik++)
9369         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9370       eright.insert(eright.end(),ees.begin(),ees.end());
9371     }
9372 }
9373
9374 /// @endcond
9375
9376 /// @cond INTERNAL
9377
9378 struct CellInfo
9379 {
9380 public:
9381   CellInfo() { }
9382   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9383 public:
9384   std::vector<int> _edges;
9385   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9386 };
9387
9388 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9389 {
9390   std::size_t nbe(edges.size());
9391   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9392   for(std::size_t i=0;i<nbe;i++)
9393     {
9394       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9395       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9396     }
9397   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9398   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9399   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9400 }
9401
9402 class EdgeInfo
9403 {
9404 public:
9405   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9406   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9407   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9408   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9409   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9410 private:
9411   int _istart;
9412   int _iend;
9413   MCAuto<MEDCouplingUMesh> _mesh;
9414   MCAuto<INTERP_KERNEL::Edge> _edge;
9415   int _left;
9416   int _right;
9417 };
9418
9419 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9420 {
9421   const MEDCouplingUMesh *mesh(_mesh);
9422   if(mesh)
9423     return ;
9424   if(_right<pos)
9425     return ;
9426   if(_left>pos)
9427     { _left++; _right++; return ; }
9428   if(_right==pos)
9429     {
9430       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9431       if((isLeft && isRight) || (!isLeft && !isRight))
9432         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9433       if(isLeft)
9434         return ;
9435       if(isRight)
9436         {
9437           _right++;
9438           return ;
9439         }
9440     }
9441   if(_left==pos)
9442     {
9443       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9444       if((isLeft && isRight) || (!isLeft && !isRight))
9445         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9446       if(isLeft)
9447         {
9448           _right++;
9449           return ;
9450         }
9451       if(isRight)
9452         {
9453           _left++;
9454           _right++;
9455           return ;
9456         }
9457     }
9458 }
9459
9460 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9461 {
9462   const MEDCouplingUMesh *mesh(_mesh);
9463   if(!mesh)
9464     {
9465       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9466     }
9467   else
9468     {// not fully splitting cell case
9469       if(mesh2D->getNumberOfCells()==1)
9470         {//little optimization. 1 cell no need to find in which cell mesh is !
9471           neighbors[0]=offset; neighbors[1]=offset;
9472           return;
9473         }
9474       else
9475         {
9476           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9477           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9478           if(cellId==-1)
9479             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9480           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9481         }
9482     }
9483 }
9484
9485 class VectorOfCellInfo
9486 {
9487 public:
9488   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9489   std::size_t size() const { return _pool.size(); }
9490   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9491   void setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs);
9492   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9493   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9494   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9495   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9496 private:
9497   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9498   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9499   const CellInfo& get(int pos) const;
9500   CellInfo& get(int pos);
9501 private:
9502   std::vector<CellInfo> _pool;
9503   MCAuto<MEDCouplingUMesh> _ze_mesh;
9504   std::vector<EdgeInfo> _edge_info;
9505 };
9506
9507 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9508 {
9509   _pool[0]._edges=edges;
9510   _pool[0]._edges_ptr=edgesPtr;
9511 }
9512
9513 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9514 {
9515   if(_pool.empty())
9516     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9517   if(_pool.size()==1)
9518     return 0;
9519   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9520   if(!zeMesh)
9521     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9522   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9523   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9524 }
9525
9526 void VectorOfCellInfo::setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs)
9527 {
9528   get(pos);//to check pos
9529   bool isFast(pos==0 && _pool.size()==1);
9530   std::size_t sz(edges.size());
9531   // dealing with edges
9532   if(sz==1)
9533     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9534   else
9535     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9536   //
9537   std::vector<CellInfo> pool(_pool.size()-1+sz);
9538   for(int i=0;i<pos;i++)
9539     pool[i]=_pool[i];
9540   for(std::size_t j=0;j<sz;j++)
9541     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9542   for(int i=pos+1;i<(int)_pool.size();i++)
9543     pool[i+sz-1]=_pool[i];
9544   _pool=pool;
9545   //
9546   if(sz==2)
9547     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9548   //
9549   if(isFast)
9550     {
9551       _ze_mesh=mesh;
9552       return ;
9553     }
9554   //
9555   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9556   if(pos>0)
9557     {
9558       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9559       ms.push_back(elt);
9560     }
9561   ms.push_back(mesh);
9562   if(pos<_ze_mesh->getNumberOfCells()-1)
9563   {
9564     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9565     ms.push_back(elt);
9566   }
9567   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9568   for(std::size_t j=0;j<ms2.size();j++)
9569     ms2[j]=ms[j];
9570   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9571 }
9572
9573 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9574 {
9575   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9576 }
9577
9578 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9579 {
9580   if(pos<0)
9581     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9582   int ret(0);
9583   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9584     {
9585       if((*it).isInMyRange(pos))
9586         return ret;
9587     }
9588   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9589 }
9590
9591 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9592 {
9593   get(pos);//to check;
9594   if(_edge_info.empty())
9595     return ;
9596   std::size_t sz(_edge_info.size()-1);
9597   for(std::size_t i=0;i<sz;i++)
9598     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9599 }
9600
9601 const CellInfo& VectorOfCellInfo::get(int pos) const
9602 {
9603   if(pos<0 || pos>=(int)_pool.size())
9604     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9605   return _pool[pos];
9606 }
9607
9608 CellInfo& VectorOfCellInfo::get(int pos)
9609 {
9610   if(pos<0 || pos>=(int)_pool.size())
9611     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9612   return _pool[pos];
9613 }
9614
9615 /*!
9616  * Given :
9617  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9618  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9619  *
9620  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9621  *
9622  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9623  *
9624  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9625  */
9626 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9627                                          MCAuto<DataArrayInt>& idsLeftRight)
9628 {
9629   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9630   if(nbCellsInSplitMesh1D==0)
9631     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9632   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9633   std::size_t nb(allEdges.size()),jj;
9634   if(nb%2!=0)
9635     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9636   std::vector<int> edge1Bis(nb*2);
9637   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9638   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9639   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9640   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9641   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9642   //
9643   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9644   int *idsLeftRightPtr(idsLeftRight->getPointer());
9645   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9646   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9647     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9648       int iEnd(iStart);
9649       for(;iEnd<nbCellsInSplitMesh1D;)
9650         {
9651           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9652           if(jj!=nb)
9653             break;
9654           else
9655             iEnd++;
9656         }
9657       if(iEnd<nbCellsInSplitMesh1D)
9658         iEnd++;
9659       //
9660       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9661       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9662       //
9663       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9664       retTmp->setCoords(splitMesh1D->getCoords());
9665       retTmp->allocateCells();
9666
9667       std::vector< std::vector<int> > out0;
9668       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9669
9670       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9671       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9672         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9673       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9674       //
9675       iStart=iEnd;
9676     }
9677   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9678     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9679   return pool.getZeMesh().retn();
9680 }
9681
9682 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9683                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9684                                      MCAuto<DataArrayInt>& idsLeftRight)
9685 {
9686   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9687   //
9688   std::vector<int> allEdges;
9689   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9690   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9691     {
9692       int edgeId(std::abs(*it)-1);
9693       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9694       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9695       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9696       if(*it>0)
9697         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9698       else
9699         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9700       std::size_t sz(edge1.size());
9701       for(std::size_t cnt=0;cnt<sz;cnt++)
9702         allEdgesPtr.push_back(ee);
9703     }
9704   //
9705   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9706 }
9707
9708 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9709 {
9710   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9711     {//easy case comparison not
9712       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9713     }
9714   else if(typ1.isQuadratic() && typ2.isQuadratic())
9715     {
9716       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9717       if(!status0)
9718         return false;
9719       if(conn1[2]==conn2[2])
9720         return true;
9721       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9722       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9723       return dist<eps;
9724     }
9725   else
9726     {//only one is quadratic
9727       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9728       if(!status0)
9729         return false;
9730       const double *a(0),*bb(0),*be(0);
9731       if(typ1.isQuadratic())
9732         {
9733           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9734         }
9735       else
9736         {
9737           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9738         }
9739       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9740       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9741       return dist<eps;
9742     }
9743 }
9744
9745 /*!
9746  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9747  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9748  *
9749  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9750  */
9751 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9752 {
9753   if(candidatesIn2DEnd==candidatesIn2DBg)
9754     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9755   const double *coo(mesh2DSplit->getCoords()->begin());
9756   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9757     return *candidatesIn2DBg;
9758   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9759   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9760   if(cellIdInMesh1DSplitRelative<0)
9761     cur1D->changeOrientationOfCells();
9762   const int *c1D(cur1D->getNodalConnectivity()->begin());
9763   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9764   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9765     {
9766       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9767       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9768       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9769       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9770       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9771       for(unsigned it2=0;it2<sz;it2++)
9772         {
9773           INTERP_KERNEL::NormalizedCellType typeOfSon;
9774           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9775           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9776           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9777             return *it;
9778         }
9779     }
9780   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9781 }
9782
9783 /// @endcond
9784
9785 /*!
9786  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9787  * 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
9788  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9789  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9790  *
9791  * \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
9792  *                      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)
9793  * \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
9794  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9795  * \param [in] eps - precision used to perform intersections and localization operations.
9796  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9797  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9798  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9799  *                               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.
9800  * \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
9801  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9802  *                               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.
9803  *
9804  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9805  */
9806 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9807 {
9808   if(!mesh2D || !mesh1D)
9809     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9810   mesh2D->checkFullyDefined();
9811   mesh1D->checkFullyDefined();
9812   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9813   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9815   // Step 1: compute all edge intersections (new nodes)
9816   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9817   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9818   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9819   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9820   //
9821   // Build desc connectivity
9822   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9823   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9824   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9825   std::map<int,int> mergedNodes;
9826   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9827   // use mergeNodes to fix intersectEdge1
9828   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9829     {
9830       std::size_t n((*it0).size()/2);
9831       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9832       std::map<int,int>::const_iterator it1;
9833       it1=mergedNodes.find(eltStart);
9834       if(it1!=mergedNodes.end())
9835         (*it0)[0]=(*it1).second;
9836       it1=mergedNodes.find(eltEnd);
9837       if(it1!=mergedNodes.end())
9838         (*it0)[2*n-1]=(*it1).second;
9839     }
9840   //
9841   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9842   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9843   // Step 2: re-order newly created nodes according to the ordering found in m2
9844   std::vector< std::vector<int> > intersectEdge2;
9845   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9846   subDiv2.clear();
9847   // Step 3: compute splitMesh1D
9848   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9849   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9850   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9851       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9852   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9853   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9854   // deal with cells in mesh2D that are not cut but only some of their edges are
9855   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
9856   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9857   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9858   MCAuto<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
9859   if(!idsInDesc2DToBeRefined->empty())
9860     {
9861       DataArrayInt *out0(0),*outi0(0);
9862       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9863       MCAuto<DataArrayInt> outi0s(outi0);
9864       out0s=out0;
9865       out0s=out0s->buildUnique();
9866       out0s->sort(true);
9867     }
9868   //
9869   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9870   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
9871   MCAuto<DataArrayInt> elts,eltsIndex;
9872   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9873   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9874   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
9875   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9876     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9877   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
9878   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9879   if((DataArrayInt *)out0s)
9880     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9881   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
9882   // OK all is ready to insert in ret2 mesh
9883   if(!untouchedCells->empty())
9884     {// the most easy part, cells in mesh2D not impacted at all
9885       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9886       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9887       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9888     }
9889   if((DataArrayInt *)out0s)
9890     {// here dealing with cells in out0s but not in cellsToBeModified
9891       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9892       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9893       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9894         {
9895           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9896           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9897         }
9898       int offset(ret2->getNumberOfTuples());
9899       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9900       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9901       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9902       int kk(0),*ret3ptr(partOfRet3->getPointer());
9903       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9904         {
9905           int faceId(std::abs(*it)-1);
9906           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9907             {
9908               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
9909               if(tmp!=-1)
9910                 {
9911                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9912                     ret3ptr[2*kk]=tmp+offset;
9913                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9914                     ret3ptr[2*kk+1]=tmp+offset;
9915                 }
9916               else
9917                 {//the current edge is shared by a 2D cell that will be split just after
9918                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9919                     ret3ptr[2*kk]=-(*it2+1);
9920                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9921                     ret3ptr[2*kk+1]=-(*it2+1);
9922                 }
9923             }
9924         }
9925       m1Desc->setCoords(ret1->getCoords());
9926       ret1NonCol->setCoords(ret1->getCoords());
9927       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9928       if(!outMesh2DSplit.empty())
9929         {
9930           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9931           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9932             (*itt)->setCoords(da);
9933         }
9934     }
9935   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9936   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9937     {
9938       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
9939       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9940       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9941       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9942       MCAuto<DataArrayInt> partOfRet3;
9943       MCAuto<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9944       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9945       outMesh2DSplit.push_back(splitOfOneCell);
9946       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9947         ret2->pushBackSilent(*it);
9948     }
9949   //
9950   std::size_t nbOfMeshes(outMesh2DSplit.size());
9951   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9952   for(std::size_t i=0;i<nbOfMeshes;i++)
9953     tmp[i]=outMesh2DSplit[i];
9954   //
9955   ret1->getCoords()->setInfoOnComponents(compNames);
9956   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9957   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9958   ret3->rearrange(1);
9959   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
9960   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9961     {
9962       int old2DCellId(-ret3->getIJ(*it,0)-1);
9963       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
9964       ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9965     }
9966   ret3->changeValue(std::numeric_limits<int>::max(),-1);
9967   ret3->rearrange(2);
9968   //
9969   splitMesh1D=ret1.retn();
9970   splitMesh2D=ret2D.retn();
9971   cellIdInMesh2D=ret2.retn();
9972   cellIdInMesh1D=ret3.retn();
9973 }
9974
9975 /**
9976  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9977  * (newly created) nodes corresponding to the edge intersections.
9978  * Output params:
9979  * @param[out] cr, crI connectivity of the resulting mesh
9980  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9981  * TODO: describe input parameters
9982  */
9983 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9984                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9985                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9986                                                          const std::vector<double>& addCoords,
9987                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9988 {
9989   static const int SPACEDIM=2;
9990   const double *coo1(m1->getCoords()->getConstPointer());
9991   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9992   int offset1(m1->getNumberOfNodes());
9993   const double *coo2(m2->getCoords()->getConstPointer());
9994   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9995   int offset2(offset1+m2->getNumberOfNodes());
9996   int offset3(offset2+((int)addCoords.size())/2);
9997   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9998   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9999   // Here a BBTree on 2D-cells, not on segments:
10000   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10001   int ncell1(m1->getNumberOfCells());
10002   crI.push_back(0);
10003   for(int i=0;i<ncell1;i++)
10004     {
10005       std::vector<int> candidates2;
10006       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10007       std::map<INTERP_KERNEL::Node *,int> mapp;
10008       std::map<int,INTERP_KERNEL::Node *> mappRev;
10009       INTERP_KERNEL::QuadraticPolygon pol1;
10010       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10011       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10012       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10013       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10014       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10015       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10016           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10017       //
10018       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
10019       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10020       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10021       for(it1.first();!it1.finished();it1.next())
10022         edges1.insert(it1.current()->getPtr());
10023       //
10024       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10025       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10026       int ii=0;
10027       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10028         {
10029           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10030           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10031           // Complete mapping with elements coming from the current cell it2 in mesh2:
10032           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10033           // pol2 is the new QP in the final merged result.
10034           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10035               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10036         }
10037       ii=0;
10038       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10039         {
10040           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10041           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10042           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10043           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10044         }
10045       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10046       // by m2 but that we still want to keep in the final result.
10047       if(!edges1.empty())
10048         {
10049           try
10050           {
10051               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10052           }
10053           catch(INTERP_KERNEL::Exception& e)
10054           {
10055               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();
10056               throw INTERP_KERNEL::Exception(oss.str().c_str());
10057           }
10058         }
10059       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10060         (*it).second->decrRef();
10061     }
10062 }
10063
10064 /**
10065  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10066  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10067  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10068  * The caller is to deal with the resulting DataArrayInt.
10069  *  \throw If the coordinate array is not set.
10070  *  \throw If the nodal connectivity of the cells is not defined.
10071  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10072  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10073  *
10074  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10075  */
10076 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10077 {
10078   checkFullyDefined();
10079   if(getMeshDimension()!=1)
10080     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10081
10082   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10083   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10084   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10085   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10086   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10087   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10088   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10089   const int * dsi(_dsi->getConstPointer());
10090   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10091   m_points=0;
10092   if (dsii->getNumberOfTuples())
10093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10094
10095   int nc(getNumberOfCells());
10096   MCAuto<DataArrayInt> result(DataArrayInt::New());
10097   result->alloc(nc,1);
10098
10099   // set of edges not used so far
10100   std::set<int> edgeSet;
10101   for (int i=0; i<nc; edgeSet.insert(i), i++);
10102
10103   int startSeg=0;
10104   int newIdx=0;
10105   // while we have points with only one neighbor segments
10106   do
10107     {
10108       std::list<int> linePiece;
10109       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10110       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10111         {
10112           // Fill the list forward (resp. backward) from the start segment:
10113           int activeSeg = startSeg;
10114           int prevPointId = -20;
10115           int ptId;
10116           while (!edgeSet.empty())
10117             {
10118               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10119                 {
10120                   if (direction==0)
10121                     linePiece.push_back(activeSeg);
10122                   else
10123                     linePiece.push_front(activeSeg);
10124                   edgeSet.erase(activeSeg);
10125                 }
10126
10127               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10128               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10129               if (dsi[ptId] == 1) // hitting the end of the line
10130                 break;
10131               prevPointId = ptId;
10132               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10133               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10134             }
10135         }
10136       // Done, save final piece into DA:
10137       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10138       newIdx += linePiece.size();
10139
10140       // identify next valid start segment (one which is not consumed)
10141       if(!edgeSet.empty())
10142         startSeg = *(edgeSet.begin());
10143     }
10144   while (!edgeSet.empty());
10145   return result.retn();
10146 }
10147
10148 /// @cond INTERNAL
10149
10150 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10151 {
10152   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10153   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10154   if(it==m.end())
10155     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10156   int v((*it).second);
10157   if(v==forbVal0 || v==forbVal1)
10158     return ;
10159   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10160     isect.push_back(v);
10161 }
10162
10163 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10164 {
10165   int sz(c.size());
10166   if(sz<=1)
10167     return false;
10168   bool presenceOfOn(false);
10169   for(int i=0;i<sz;i++)
10170     {
10171       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10172       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10173         continue ;
10174       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10175       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10176     }
10177   return presenceOfOn;
10178 }
10179
10180 /// @endcond
10181
10182 /**
10183  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10184  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10185  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10186  * a minimal creation of new nodes is wanted.
10187  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10188  * nodes if a SEG3 is split without information of middle.
10189  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10190  * avoid to have a non conform mesh.
10191  *
10192  * \return int - the number of new nodes created (in most of cases 0).
10193  * 
10194  * \throw If \a this is not coherent.
10195  * \throw If \a this has not spaceDim equal to 2.
10196  * \throw If \a this has not meshDim equal to 2.
10197  * \throw If some subcells needed to be split are orphan.
10198  * \sa MEDCouplingUMesh::conformize2D
10199  */
10200 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10201 {
10202   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10203     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10204   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10205   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10206     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10207   if(midOpt==0 && midOptI==0)
10208     {
10209       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10210       return 0;
10211     }
10212   else if(midOpt!=0 && midOptI!=0)
10213     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10214   else
10215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10216 }
10217
10218 /*!
10219  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10220  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10221  * 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
10222  * 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).
10223  * 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.
10224  * 
10225  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10226  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10227  *
10228  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10229  * This method expects that all nodes in \a this are not closer than \a eps.
10230  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10231  * 
10232  * \param [in] eps the relative error to detect merged edges.
10233  * \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
10234  *                           that the user is expected to deal with.
10235  *
10236  * \throw If \a this is not coherent.
10237  * \throw If \a this has not spaceDim equal to 2.
10238  * \throw If \a this has not meshDim equal to 2.
10239  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10240  */
10241 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10242 {
10243   static const int SPACEDIM=2;
10244   checkConsistencyLight();
10245   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10247   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10248   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10249   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10250   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10251   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10252   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10253   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10254   std::vector<double> addCoo;
10255   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10256   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10257   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10258   for(int i=0;i<nDescCell;i++)
10259     {
10260       std::vector<int> candidates;
10261       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10262       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10263         if(*it>i)
10264           {
10265             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10266             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10267                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10268             INTERP_KERNEL::MergePoints merge;
10269             INTERP_KERNEL::QuadraticPolygon c1,c2;
10270             e1->intersectWith(e2,merge,c1,c2);
10271             e1->decrRef(); e2->decrRef();
10272             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10273               overlapEdge[i].push_back(*it);
10274             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10275               overlapEdge[*it].push_back(i);
10276           }
10277     }
10278   // splitting done. sort intersect point in intersectEdge.
10279   std::vector< std::vector<int> > middle(nDescCell);
10280   int nbOf2DCellsToBeSplit(0);
10281   bool middleNeedsToBeUsed(false);
10282   std::vector<bool> cells2DToTreat(nDescCell,false);
10283   for(int i=0;i<nDescCell;i++)
10284     {
10285       std::vector<int>& isect(intersectEdge[i]);
10286       int sz((int)isect.size());
10287       if(sz>1)
10288         {
10289           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10290           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10291           e->sortSubNodesAbs(coords,isect);
10292           e->decrRef();
10293         }
10294       if(sz!=0)
10295         {
10296           int idx0(rdi[i]),idx1(rdi[i+1]);
10297           if(idx1-idx0!=1)
10298             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10299           if(!cells2DToTreat[rd[idx0]])
10300             {
10301               cells2DToTreat[rd[idx0]]=true;
10302               nbOf2DCellsToBeSplit++;
10303             }
10304           // try to reuse at most eventual 'middle' of SEG3
10305           std::vector<int>& mid(middle[i]);
10306           mid.resize(sz+1,-1);
10307           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10308             {
10309               middleNeedsToBeUsed=true;
10310               const std::vector<int>& candidates(overlapEdge[i]);
10311               std::vector<int> trueCandidates;
10312               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10313                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10314                   trueCandidates.push_back(*itc);
10315               int stNode(c[ci[i]+1]),endNode(isect[0]);
10316               for(int j=0;j<sz+1;j++)
10317                 {
10318                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10319                     {
10320                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10321                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10322                         { mid[j]=*itc; break; }
10323                     }
10324                   stNode=endNode;
10325                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10326                 }
10327             }
10328         }
10329     }
10330   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10331   if(nbOf2DCellsToBeSplit==0)
10332     return ret.retn();
10333   //
10334   int *retPtr(ret->getPointer());
10335   for(int i=0;i<nCell;i++)
10336     if(cells2DToTreat[i])
10337       *retPtr++=i;
10338   //
10339   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10340   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10341   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10342   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10343   if(middleNeedsToBeUsed)
10344     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10345   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10346   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10347   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.
10348   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10349   {
10350     bool areNodesMerged; int newNbOfNodes;
10351     if(nbOfNodesCreated!=0)
10352       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10353   }
10354   return ret.retn();
10355 }
10356
10357 /*!
10358  * 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.
10359  * 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).
10360  * 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
10361  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10362  * 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
10363  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10364  *
10365  * 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
10366  * using new instance, idem for coordinates.
10367  *
10368  * 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.
10369  * 
10370  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10371  *
10372  * \throw If \a this is not coherent.
10373  * \throw If \a this has not spaceDim equal to 2.
10374  * \throw If \a this has not meshDim equal to 2.
10375  * 
10376  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10377  */
10378 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10379 {
10380   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10381   checkConsistencyLight();
10382   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10383     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10384   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10385   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10386   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10387   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10388   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10389   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10390   const double *coords(_coords->begin());
10391   int *newciptr(newci->getPointer());
10392   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10393     {
10394       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10395         ret->pushBackSilent(i);
10396       newciptr[1]=newc->getNumberOfTuples();
10397     }
10398   //
10399   if(ret->empty())
10400     return ret.retn();
10401   if(!appendedCoords->empty())
10402     {
10403       appendedCoords->rearrange(2);
10404       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10405       //non const part
10406       setCoords(newCoords);
10407     }
10408   //non const part
10409   setConnectivity(newc,newci,true);
10410   return ret.retn();
10411 }
10412
10413 /*!
10414  * \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.
10415  *                               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.
10416  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10417  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10418  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10419  * \param [out] addCoo - nodes to be append at the end
10420  * \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.
10421  */
10422 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10423                                          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)
10424 {
10425   static const int SPACEDIM=2;
10426   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10427   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10428   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10429   // Build BB tree of all edges in the tool mesh (second mesh)
10430   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10431   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10432   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10433   intersectEdge1.resize(nDescCell1);
10434   colinear2.resize(nDescCell2);
10435   subDiv2.resize(nDescCell2);
10436   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10437
10438   std::vector<int> candidates1(1);
10439   int offset1(m1Desc->getNumberOfNodes());
10440   int offset2(offset1+m2Desc->getNumberOfNodes());
10441   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10442     {
10443       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10444       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10445       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10446         {
10447           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10448           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10449           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10450           candidates1[0]=i;
10451           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10452           // 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
10453           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10454           std::set<INTERP_KERNEL::Node *> nodes;
10455           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10456           std::size_t szz(nodes.size());
10457           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10458           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10459           for(std::size_t iii=0;iii<szz;iii++,itt++)
10460             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10461           // end of protection
10462           // Performs egde cutting:
10463           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10464           delete pol2;
10465           delete pol1;
10466         }
10467       else
10468         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10469         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10470     }
10471 }
10472
10473 /*!
10474  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10475  * It builds the descending connectivity of the two meshes, and then using a binary tree
10476  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10477  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10478  */
10479 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10480                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10481                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10482                                                    std::vector<double>& addCoo,
10483                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10484 {
10485   // Build desc connectivity
10486   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10487   desc2=DataArrayInt::New();
10488   descIndx2=DataArrayInt::New();
10489   revDesc2=DataArrayInt::New();
10490   revDescIndx2=DataArrayInt::New();
10491   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10492   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10493   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10494   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10495   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10496   std::map<int,int> notUsedMap;
10497   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10498   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10499   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10500 }
10501
10502 /*!
10503  * This method performs the 2nd step of Partition of 2D mesh.
10504  * This method has 4 inputs :
10505  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10506  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10507  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10508  * 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'
10509  * Nodes end up lying consecutively on a cutted edge.
10510  * \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.
10511  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10512  * \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.
10513  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10514  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10515  */
10516 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10517                                            const std::vector<double>& addCoo,
10518                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10519 {
10520   int offset1=m1->getNumberOfNodes();
10521   int ncell=m2->getNumberOfCells();
10522   const int *c=m2->getNodalConnectivity()->getConstPointer();
10523   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10524   const double *coo=m2->getCoords()->getConstPointer();
10525   const double *cooBis=m1->getCoords()->getConstPointer();
10526   int offset2=offset1+m2->getNumberOfNodes();
10527   intersectEdge.resize(ncell);
10528   for(int i=0;i<ncell;i++,cI++)
10529     {
10530       const std::vector<int>& divs=subDiv[i];
10531       int nnode=cI[1]-cI[0]-1;
10532       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10533       std::map<INTERP_KERNEL::Node *, int> mapp22;
10534       for(int j=0;j<nnode;j++)
10535         {
10536           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10537           int nnid=c[(*cI)+j+1];
10538           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10539           mapp22[nn]=nnid+offset1;
10540         }
10541       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10542       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10543         ((*it).second.first)->decrRef();
10544       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10545       std::map<INTERP_KERNEL::Node *,int> mapp3;
10546       for(std::size_t j=0;j<divs.size();j++)
10547         {
10548           int id=divs[j];
10549           INTERP_KERNEL::Node *tmp=0;
10550           if(id<offset1)
10551             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10552           else if(id<offset2)
10553             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10554           else
10555             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10556           addNodes[j]=tmp;
10557           mapp3[tmp]=id;
10558         }
10559       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10560       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10561         (*it)->decrRef();
10562       e->decrRef();
10563     }
10564 }
10565
10566 /*!
10567  * 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).
10568  * 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
10569  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10570  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10571  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10572  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10573  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10574  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10575  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10576  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10577  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10578  * \param [out] cut3DSuf input/output param.
10579  */
10580 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10581                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10582                                                    const int *desc, const int *descIndx, 
10583                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10584 {
10585   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10586   int nbOf3DSurfCell=(int)cut3DSurf.size();
10587   for(int i=0;i<nbOf3DSurfCell;i++)
10588     {
10589       std::vector<int> res;
10590       int offset=descIndx[i];
10591       int nbOfSeg=descIndx[i+1]-offset;
10592       for(int j=0;j<nbOfSeg;j++)
10593         {
10594           int edgeId=desc[offset+j];
10595           int status=cut3DCurve[edgeId];
10596           if(status!=-2)
10597             {
10598               if(status>-1)
10599                 res.push_back(status);
10600               else
10601                 {
10602                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10603                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10604                 }
10605             }
10606         }
10607       switch(res.size())
10608       {
10609         case 2:
10610           {
10611             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10612             break;
10613           }
10614         case 1:
10615         case 0:
10616           {
10617             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10618             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10619             if(res.size()==2)
10620               {
10621                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10622               }
10623             else
10624               {
10625                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10626               }
10627             break;
10628           }
10629         default:
10630           {// case when plane is on a multi colinear edge of a polyhedron
10631             if((int)res.size()==2*nbOfSeg)
10632               {
10633                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10634               }
10635             else
10636               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10637           }
10638       }
10639     }
10640 }
10641
10642 /*!
10643  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10644  * 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).
10645  * 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
10646  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10647  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10648  * \param desc is the descending connectivity 3D->3DSurf
10649  * \param descIndx is the descending connectivity index 3D->3DSurf
10650  */
10651 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10652                                                   const int *desc, const int *descIndx,
10653                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10654 {
10655   checkFullyDefined();
10656   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10657     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10658   const int *nodal3D=_nodal_connec->getConstPointer();
10659   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10660   int nbOfCells=getNumberOfCells();
10661   for(int i=0;i<nbOfCells;i++)
10662     {
10663       std::map<int, std::set<int> > m;
10664       int offset=descIndx[i];
10665       int nbOfFaces=descIndx[i+1]-offset;
10666       int start=-1;
10667       int end=-1;
10668       for(int j=0;j<nbOfFaces;j++)
10669         {
10670           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10671           if(p.first!=-1 && p.second!=-1)
10672             {
10673               if(p.first!=-2)
10674                 {
10675                   start=p.first; end=p.second;
10676                   m[p.first].insert(p.second);
10677                   m[p.second].insert(p.first);
10678                 }
10679               else
10680                 {
10681                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10682                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10683                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10684                   INTERP_KERNEL::NormalizedCellType cmsId;
10685                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10686                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10687                   for(unsigned k=0;k<nbOfNodesSon;k++)
10688                     {
10689                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10690                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10691                     }
10692                 }
10693             }
10694         }
10695       if(m.empty())
10696         continue;
10697       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10698       int prev=end;
10699       while(end!=start)
10700         {
10701           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10702           const std::set<int>& s=(*it).second;
10703           std::set<int> s2; s2.insert(prev);
10704           std::set<int> s3;
10705           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10706           if(s3.size()==1)
10707             {
10708               int val=*s3.begin();
10709               conn.push_back(start);
10710               prev=start;
10711               start=val;
10712             }
10713           else
10714             start=end;
10715         }
10716       conn.push_back(end);
10717       if(conn.size()>3)
10718         {
10719           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10720           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10721           cellIds->pushBackSilent(i);
10722         }
10723     }
10724 }
10725
10726 /*!
10727  * 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
10728  * 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
10729  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10730  * 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
10731  * 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.
10732  * 
10733  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10734  */
10735 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10736 {
10737   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10738   if(sz>=4)
10739     {
10740       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10741       if(cm.getDimension()==2)
10742         {
10743           const int *node=nodalConnBg+1;
10744           int startNode=*node++;
10745           double refX=coords[2*startNode];
10746           for(;node!=nodalConnEnd;node++)
10747             {
10748               if(coords[2*(*node)]<refX)
10749                 {
10750                   startNode=*node;
10751                   refX=coords[2*startNode];
10752                 }
10753             }
10754           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10755           refX=1e300;
10756           double tmp1;
10757           double tmp2[2];
10758           double angle0=-M_PI/2;
10759           //
10760           int nextNode=-1;
10761           int prevNode=-1;
10762           double resRef;
10763           double angleNext=0.;
10764           while(nextNode!=startNode)
10765             {
10766               nextNode=-1;
10767               resRef=1e300;
10768               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10769                 {
10770                   if(*node!=tmpOut.back() && *node!=prevNode)
10771                     {
10772                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10773                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10774                       double res;
10775                       if(angleM<=angle0)
10776                         res=angle0-angleM;
10777                       else
10778                         res=angle0-angleM+2.*M_PI;
10779                       if(res<resRef)
10780                         {
10781                           nextNode=*node;
10782                           resRef=res;
10783                           angleNext=angleM;
10784                         }
10785                     }
10786                 }
10787               if(nextNode!=startNode)
10788                 {
10789                   angle0=angleNext-M_PI;
10790                   if(angle0<-M_PI)
10791                     angle0+=2*M_PI;
10792                   prevNode=tmpOut.back();
10793                   tmpOut.push_back(nextNode);
10794                 }
10795             }
10796           std::vector<int> tmp3(2*(sz-1));
10797           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10798           std::copy(nodalConnBg+1,nodalConnEnd,it);
10799           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10800             {
10801               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10802               return false;
10803             }
10804           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10805             {
10806               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10807               return false;
10808             }
10809           else
10810             {
10811               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10812               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10813               return true;
10814             }
10815         }
10816       else
10817         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10818     }
10819   else
10820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10821 }
10822
10823 /*!
10824  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10825  * 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.
10826  * 
10827  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10828  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10829  * \param [in,out] arr array in which the remove operation will be done.
10830  * \param [in,out] arrIndx array in the remove operation will modify
10831  * \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])
10832  * \return true if \b arr and \b arrIndx have been modified, false if not.
10833  */
10834 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10835 {
10836   if(!arrIndx || !arr)
10837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10838   if(offsetForRemoval<0)
10839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10840   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10841   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10842   int *arrIPtr=arrIndx->getPointer();
10843   *arrIPtr++=0;
10844   int previousArrI=0;
10845   const int *arrPtr=arr->getConstPointer();
10846   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10847   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10848     {
10849       if(*arrIPtr-previousArrI>offsetForRemoval)
10850         {
10851           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10852             {
10853               if(s.find(*work)==s.end())
10854                 arrOut.push_back(*work);
10855             }
10856         }
10857       previousArrI=*arrIPtr;
10858       *arrIPtr=(int)arrOut.size();
10859     }
10860   if(arr->getNumberOfTuples()==(int)arrOut.size())
10861     return false;
10862   arr->alloc((int)arrOut.size(),1);
10863   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10864   return true;
10865 }
10866
10867 /*!
10868  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10869  * (\ref numbering-indirect).
10870  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10871  * The selection of extraction is done standardly in new2old format.
10872  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10873  *
10874  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10875  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10876  * \param [in] arrIn arr origin array from which the extraction will be done.
10877  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10878  * \param [out] arrOut the resulting array
10879  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10880  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
10881  */
10882 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10883                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10884 {
10885   if(!arrIn || !arrIndxIn)
10886     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10887   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10888   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10890   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10891   const int *arrInPtr=arrIn->getConstPointer();
10892   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10893   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10894   if(nbOfGrps<0)
10895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10896   int maxSizeOfArr=arrIn->getNumberOfTuples();
10897   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10898   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10899   arrIo->alloc((int)(sz+1),1);
10900   const int *idsIt=idsOfSelectBg;
10901   int *work=arrIo->getPointer();
10902   *work++=0;
10903   int lgth=0;
10904   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10905     {
10906       if(*idsIt>=0 && *idsIt<nbOfGrps)
10907         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10908       else
10909         {
10910           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10911           throw INTERP_KERNEL::Exception(oss.str().c_str());
10912         }
10913       if(lgth>=work[-1])
10914         *work=lgth;
10915       else
10916         {
10917           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10918           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10919           throw INTERP_KERNEL::Exception(oss.str().c_str());
10920         }
10921     }
10922   arro->alloc(lgth,1);
10923   work=arro->getPointer();
10924   idsIt=idsOfSelectBg;
10925   for(std::size_t i=0;i<sz;i++,idsIt++)
10926     {
10927       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10928         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10929       else
10930         {
10931           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10932           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10933           throw INTERP_KERNEL::Exception(oss.str().c_str());
10934         }
10935     }
10936   arrOut=arro.retn();
10937   arrIndexOut=arrIo.retn();
10938 }
10939
10940 /*!
10941  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10942  * (\ref numbering-indirect).
10943  * 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 ).
10944  * The selection of extraction is done standardly in new2old format.
10945  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10946  *
10947  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10948  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10949  * \param [in] idsOfSelectStep
10950  * \param [in] arrIn arr origin array from which the extraction will be done.
10951  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10952  * \param [out] arrOut the resulting array
10953  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10954  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10955  */
10956 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10957                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10958 {
10959   if(!arrIn || !arrIndxIn)
10960     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
10961   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10962   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
10964   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
10965   const int *arrInPtr=arrIn->getConstPointer();
10966   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10967   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10968   if(nbOfGrps<0)
10969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10970   int maxSizeOfArr=arrIn->getNumberOfTuples();
10971   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10972   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10973   arrIo->alloc((int)(sz+1),1);
10974   int idsIt=idsOfSelectStart;
10975   int *work=arrIo->getPointer();
10976   *work++=0;
10977   int lgth=0;
10978   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10979     {
10980       if(idsIt>=0 && idsIt<nbOfGrps)
10981         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10982       else
10983         {
10984           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10985           throw INTERP_KERNEL::Exception(oss.str().c_str());
10986         }
10987       if(lgth>=work[-1])
10988         *work=lgth;
10989       else
10990         {
10991           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10992           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10993           throw INTERP_KERNEL::Exception(oss.str().c_str());
10994         }
10995     }
10996   arro->alloc(lgth,1);
10997   work=arro->getPointer();
10998   idsIt=idsOfSelectStart;
10999   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11000     {
11001       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11002         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11003       else
11004         {
11005           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11006           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11007           throw INTERP_KERNEL::Exception(oss.str().c_str());
11008         }
11009     }
11010   arrOut=arro.retn();
11011   arrIndexOut=arrIo.retn();
11012 }
11013
11014 /*!
11015  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11016  * 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
11017  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11018  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11019  *
11020  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11021  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11022  * \param [in] arrIn arr origin array from which the extraction will be done.
11023  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11024  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11025  * \param [in] srcArrIndex index array of \b srcArr
11026  * \param [out] arrOut the resulting array
11027  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11028  * 
11029  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11030  */
11031 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11032                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11033                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11034 {
11035   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11037   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11038   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11039   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11040   std::vector<bool> v(nbOfTuples,true);
11041   int offset=0;
11042   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11043   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11044   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11045     {
11046       if(*it>=0 && *it<nbOfTuples)
11047         {
11048           v[*it]=false;
11049           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11050         }
11051       else
11052         {
11053           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11054           throw INTERP_KERNEL::Exception(oss.str().c_str());
11055         }
11056     }
11057   srcArrIndexPtr=srcArrIndex->getConstPointer();
11058   arrIo->alloc(nbOfTuples+1,1);
11059   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11060   const int *arrInPtr=arrIn->getConstPointer();
11061   const int *srcArrPtr=srcArr->getConstPointer();
11062   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11063   int *arroPtr=arro->getPointer();
11064   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11065     {
11066       if(v[ii])
11067         {
11068           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11069           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11070         }
11071       else
11072         {
11073           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11074           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11075           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11076         }
11077     }
11078   arrOut=arro.retn();
11079   arrIndexOut=arrIo.retn();
11080 }
11081
11082 /*!
11083  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11084  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11085  *
11086  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11087  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11088  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11089  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11090  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11091  * \param [in] srcArrIndex index array of \b srcArr
11092  * 
11093  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11094  */
11095 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11096                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11097 {
11098   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11099     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11100   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11101   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11102   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11103   int *arrInOutPtr=arrInOut->getPointer();
11104   const int *srcArrPtr=srcArr->getConstPointer();
11105   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11106     {
11107       if(*it>=0 && *it<nbOfTuples)
11108         {
11109           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11110             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11111           else
11112             {
11113               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] !";
11114               throw INTERP_KERNEL::Exception(oss.str().c_str());
11115             }
11116         }
11117       else
11118         {
11119           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11120           throw INTERP_KERNEL::Exception(oss.str().c_str());
11121         }
11122     }
11123 }
11124
11125 /*!
11126  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11127  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11128  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11129  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11130  * A negative value in \b arrIn means that it is ignored.
11131  * 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.
11132  * 
11133  * \param [in] arrIn arr origin array from which the extraction will be done.
11134  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11135  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11136  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11137  */
11138 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11139 {
11140   int seed=0,nbOfDepthPeelingPerformed=0;
11141   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11142 }
11143
11144 /*!
11145  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11146  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11147  * 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]].
11148  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11149  * A negative value in \b arrIn means that it is ignored.
11150  * 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.
11151  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11152  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11153  * \param [in] arrIn arr origin array from which the extraction will be done.
11154  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11155  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11156  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11157  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11158  * \sa MEDCouplingUMesh::partitionBySpreadZone
11159  */
11160 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11161 {
11162   nbOfDepthPeelingPerformed=0;
11163   if(!arrIndxIn)
11164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11165   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11166   if(nbOfTuples<=0)
11167     {
11168       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11169       return ret;
11170     }
11171   //
11172   std::vector<bool> fetched(nbOfTuples,false);
11173   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11174 }
11175
11176 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11177 {
11178   nbOfDepthPeelingPerformed=0;
11179   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11180     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11181   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11182   std::vector<bool> fetched2(nbOfTuples,false);
11183   int i=0;
11184   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11185     {
11186       if(*seedElt>=0 && *seedElt<nbOfTuples)
11187         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11188       else
11189         { 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()); }
11190     }
11191   const int *arrInPtr=arrIn->getConstPointer();
11192   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11193   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11194   std::vector<int> idsToFetch1(seedBg,seedEnd);
11195   std::vector<int> idsToFetch2;
11196   std::vector<int> *idsToFetch=&idsToFetch1;
11197   std::vector<int> *idsToFetchOther=&idsToFetch2;
11198   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11199     {
11200       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11201         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11202           if(!fetched[*it2])
11203             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11204       std::swap(idsToFetch,idsToFetchOther);
11205       idsToFetchOther->clear();
11206       nbOfDepthPeelingPerformed++;
11207     }
11208   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11209   i=0;
11210   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11211   int *retPtr=ret->getPointer();
11212   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11213     if(*it)
11214       *retPtr++=i;
11215   return ret.retn();
11216 }
11217
11218 /*!
11219  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11220  * 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
11221  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11222  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11223  *
11224  * \param [in] start begin of set of ids of the input extraction (included)
11225  * \param [in] end end of set of ids of the input extraction (excluded)
11226  * \param [in] step step of the set of ids in range mode.
11227  * \param [in] arrIn arr origin array from which the extraction will be done.
11228  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11229  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11230  * \param [in] srcArrIndex index array of \b srcArr
11231  * \param [out] arrOut the resulting array
11232  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11233  * 
11234  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11235  */
11236 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11237                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11238                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11239 {
11240   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11242   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11243   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11244   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11245   int offset=0;
11246   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11247   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11248   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11249   int it=start;
11250   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11251     {
11252       if(it>=0 && it<nbOfTuples)
11253         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11254       else
11255         {
11256           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11257           throw INTERP_KERNEL::Exception(oss.str().c_str());
11258         }
11259     }
11260   srcArrIndexPtr=srcArrIndex->getConstPointer();
11261   arrIo->alloc(nbOfTuples+1,1);
11262   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11263   const int *arrInPtr=arrIn->getConstPointer();
11264   const int *srcArrPtr=srcArr->getConstPointer();
11265   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11266   int *arroPtr=arro->getPointer();
11267   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11268     {
11269       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11270       if(pos<0)
11271         {
11272           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11273           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11274         }
11275       else
11276         {
11277           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11278           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11279         }
11280     }
11281   arrOut=arro.retn();
11282   arrIndexOut=arrIo.retn();
11283 }
11284
11285 /*!
11286  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11287  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11288  *
11289  * \param [in] start begin of set of ids of the input extraction (included)
11290  * \param [in] end end of set of ids of the input extraction (excluded)
11291  * \param [in] step step of the set of ids in range mode.
11292  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11293  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11294  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11295  * \param [in] srcArrIndex index array of \b srcArr
11296  * 
11297  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11298  */
11299 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11300                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11301 {
11302   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11303     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11304   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11305   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11306   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11307   int *arrInOutPtr=arrInOut->getPointer();
11308   const int *srcArrPtr=srcArr->getConstPointer();
11309   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11310   int it=start;
11311   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11312     {
11313       if(it>=0 && it<nbOfTuples)
11314         {
11315           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11316             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11317           else
11318             {
11319               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11320               throw INTERP_KERNEL::Exception(oss.str().c_str());
11321             }
11322         }
11323       else
11324         {
11325           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11326           throw INTERP_KERNEL::Exception(oss.str().c_str());
11327         }
11328     }
11329 }
11330
11331 /*!
11332  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11333  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11334  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11335  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11336  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11337  * 
11338  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11339  */
11340 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11341 {
11342   checkFullyDefined();
11343   int mdim=getMeshDimension();
11344   int spaceDim=getSpaceDimension();
11345   if(mdim!=spaceDim)
11346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11347   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11348   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11349   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11350   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11351   ret->setCoords(getCoords());
11352   ret->allocateCells((int)partition.size());
11353   //
11354   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11355     {
11356       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11357       MCAuto<DataArrayInt> cell;
11358       switch(mdim)
11359       {
11360         case 2:
11361           cell=tmp->buildUnionOf2DMesh();
11362           break;
11363         case 3:
11364           cell=tmp->buildUnionOf3DMesh();
11365           break;
11366         default:
11367           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11368       }
11369
11370       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11371     }
11372   //
11373   ret->finishInsertingCells();
11374   return ret.retn();
11375 }
11376
11377 /*!
11378  * This method partitions \b this into contiguous zone.
11379  * This method only needs a well defined connectivity. Coordinates are not considered here.
11380  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11381  */
11382 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11383 {
11384   int nbOfCellsCur=getNumberOfCells();
11385   std::vector<DataArrayInt *> ret;
11386   if(nbOfCellsCur<=0)
11387     return ret;
11388   DataArrayInt *neigh=0,*neighI=0;
11389   computeNeighborsOfCells(neigh,neighI);
11390   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11391   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11392   std::vector< MCAuto<DataArrayInt> > ret2;
11393   int seed=0;
11394   while(seed<nbOfCellsCur)
11395     {
11396       int nbOfPeelPerformed=0;
11397       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11398       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11399     }
11400   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11401     ret.push_back((*it).retn());
11402   return ret;
11403 }
11404
11405 /*!
11406  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11407  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11408  *
11409  * \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.
11410  * \return a newly allocated DataArrayInt to be managed by the caller.
11411  * \throw In case of \a code has not the right format (typically of size 3*n)
11412  */
11413 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11414 {
11415   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11416   std::size_t nb=code.size()/3;
11417   if(code.size()%3!=0)
11418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11419   ret->alloc((int)nb,2);
11420   int *retPtr=ret->getPointer();
11421   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11422     {
11423       retPtr[0]=code[3*i+2];
11424       retPtr[1]=code[3*i+2]+code[3*i+1];
11425     }
11426   return ret.retn();
11427 }
11428
11429 /*!
11430  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11431  * All cells in \a this are expected to be linear 3D cells.
11432  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11433  * It leads to an increase to number of cells.
11434  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11435  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11436  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11437  *
11438  * \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.
11439  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11440  * \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. 
11441  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11442  *          an id of old cell producing it. The caller is to delete this array using
11443  *         decrRef() as it is no more needed.
11444  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11445  *
11446  * \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
11447  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11448  * 
11449  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11450  * \throw If \a this is not fully constituted with linear 3D cells.
11451  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11452  */
11453 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11454 {
11455   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11456   checkConnectivityFullyDefined();
11457   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11459   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11460   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11461   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11462   int *retPt(ret->getPointer());
11463   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11464   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11465   const int *oldc(_nodal_connec->begin());
11466   const int *oldci(_nodal_connec_index->begin());
11467   const double *coords(_coords->begin());
11468   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11469     {
11470       std::vector<int> a; std::vector<double> b;
11471       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11472       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11473       const int *aa(&a[0]);
11474       if(!b.empty())
11475         {
11476           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11477             if(*it<0)
11478               *it=(-(*(it))-1+nbNodes);
11479           addPts->insertAtTheEnd(b.begin(),b.end());
11480           nbNodes+=(int)b.size()/3;
11481         }
11482       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11483         newConn->insertAtTheEnd(aa,aa+4);
11484     }
11485   if(!addPts->empty())
11486     {
11487       addPts->rearrange(3);
11488       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11489       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11490       ret0->setCoords(addPts);
11491     }
11492   else
11493     {
11494       nbOfAdditionalPoints=0;
11495       ret0->setCoords(getCoords());
11496     }
11497   ret0->setNodalConnectivity(newConn);
11498   //
11499   ret->computeOffsetsFull();
11500   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11501   return ret0.retn();
11502 }
11503
11504 /*!
11505  * 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). 
11506  *
11507  * \sa MEDCouplingUMesh::split2DCells
11508  */
11509 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11510 {
11511   checkConnectivityFullyDefined();
11512   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11513   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11514   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11515   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11516   int prevPosOfCi(ciPtr[0]);
11517   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11518     {
11519       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11520       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11521       for(int j=0;j<sz;j++)
11522         {
11523           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11524           for(int k=0;k<sz2;k++)
11525             *cPtr++=subPtr[offset2+k];
11526           if(j!=sz-1)
11527             *cPtr++=oldConn[prevPosOfCi+j+2];
11528           deltaSz+=sz2;
11529         }
11530       prevPosOfCi=ciPtr[1];
11531       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11532     }
11533   if(c->end()!=cPtr)
11534     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11535   _nodal_connec->decrRef();
11536   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11537 }
11538
11539 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11540 {
11541   if(id!=-1)
11542     return id;
11543   else
11544     {
11545       int ret(nodesCnter++);
11546       double newPt[2];
11547       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11548       addCoo.insertAtTheEnd(newPt,newPt+2);
11549       return ret;
11550     }
11551 }
11552
11553 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11554 {
11555   if(id!=-1)
11556     return id;
11557   else
11558     {
11559       int ret(nodesCnter++);
11560       double newPt[2];
11561       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11562       addCoo.insertAtTheEnd(newPt,newPt+2);
11563       return ret;
11564     }
11565 }
11566
11567
11568 /// @cond INTERNAL
11569
11570 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)
11571 {
11572   int tmp[3];
11573   int trueStart(start>=0?start:nbOfEdges+start);
11574   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11575   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11576   if(linOrArc)
11577     {
11578       if(stp-start>1)
11579         {
11580           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11581           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11582           middles.push_back(tmp3+offset);
11583         }
11584       else
11585         middles.push_back(connBg[trueStart+nbOfEdges]);
11586     }
11587 }
11588
11589 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)
11590 {
11591   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11592   newConnOfCell->pushBackSilent(tmpEnd);
11593   if(linOrArc)
11594     {
11595       if(stp-start>1)
11596         {
11597           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11598           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11599           middles.push_back(tmp3+offset);
11600         }
11601       else
11602         middles.push_back(connBg[start+nbOfEdges]);
11603     }
11604 }
11605
11606 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)
11607 {
11608   // only the quadratic point to deal with:
11609   if(linOrArc)
11610     {
11611       if(stp-start>1)
11612         {
11613           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11614           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11615           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11616           middles.push_back(tmp3+offset);
11617         }
11618       else
11619         middles.push_back(connBg[start+nbOfEdges]);
11620     }
11621 }
11622
11623 /// @endcond
11624
11625 /*!
11626  * 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 ) .
11627  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11628  */
11629 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11630 {
11631   std::size_t sz(std::distance(connBg,connEnd));
11632   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11633     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11634   sz--;
11635   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11636   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11637   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11638   unsigned nbOfHit(0); // number of fusions operated
11639   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11640   const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3;  // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least
11641   INTERP_KERNEL::NormalizedCellType typeOfSon;
11642   std::vector<int> middles;
11643   bool ret(false);
11644   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11645     {
11646       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11647       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11648       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11649       posEndElt = posBaseElt+1;
11650
11651       // Look backward first: are the final edges of the cells colinear with the first ones?
11652       // This initializes posBaseElt.
11653       if(nbOfTurn==0)
11654         {
11655           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11656             {
11657               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11658               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11659               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11660               bool isColinear=eint->areColinears();
11661               if(isColinear)
11662                 {
11663                   nbOfHit++;
11664                   posBaseElt--;
11665                   ret=true;
11666                 }
11667               delete eint;
11668               eCand->decrRef();
11669               if(!isColinear)
11670                 break;
11671             }
11672         }
11673       // Now move forward:
11674       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11675       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11676         {
11677           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11678           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11679           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11680           bool isColinear(eint->areColinears());
11681           if(isColinear)
11682             {
11683               nbOfHit++;
11684               posEndElt++;
11685               ret=true;
11686             }
11687           delete eint;
11688           eCand->decrRef();
11689           if(!isColinear)
11690               break;
11691         }
11692       //push [posBaseElt,posEndElt) in newConnOfCell using e
11693       // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining!
11694       if(nbOfTurn==0)
11695         // at the begining of the connectivity (insert type)
11696         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11697       else if((nbOfHit+nbOfTurn) != (nbs-1))
11698         // in the middle
11699         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11700       if ((nbOfHit+nbOfTurn) == (nbs-1))
11701         // at the end (only quad points to deal with)
11702         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11703       posBaseElt=posEndElt;
11704       e->decrRef();
11705     }
11706   if(!middles.empty())
11707     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11708   return ret;
11709 }
11710
11711 /*!
11712  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11713  *
11714  * \return  int - the number of new nodes created.
11715  * \sa MEDCouplingUMesh::split2DCells
11716  */
11717 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11718 {
11719   checkConsistencyLight();
11720   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11721   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11722   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11723   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11724   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11725   const double *oldCoordsPtr(getCoords()->begin());
11726   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11727   int prevPosOfCi(ciPtr[0]);
11728   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11729     {
11730       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11731       for(int j=0;j<sz;j++)
11732         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11733       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11734       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11735         {
11736           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11737           if(sz2==0)
11738             {
11739               if(j<sz-1)
11740                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11741               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11742               continue;
11743             }
11744           std::vector<INTERP_KERNEL::Node *> ns(3);
11745           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11746           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11747           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11748           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11749           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11750             {
11751               cPtr[1]=subPtr[offset2+k];
11752               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11753             }
11754           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11755           if(j!=sz-1)
11756             { cPtr[1]=tmpEnd; }
11757           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11758         }
11759       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11760       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11761     }
11762   if(c->end()!=cPtr)
11763     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11764   _nodal_connec->decrRef();
11765   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11766   addCoo->rearrange(2);
11767   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11768   setCoords(coo);
11769   return addCoo->getNumberOfTuples();
11770 }
11771
11772 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11773 {
11774   if(nodalConnec && nodalConnecIndex)
11775     {
11776       types.clear();
11777       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11778       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11779       if(nbOfElem>0)
11780         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11781           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11782     }
11783 }
11784
11785 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11786     _own_cell(true),_cell_id(-1),_nb_cell(0)
11787 {
11788   if(mesh)
11789     {
11790       mesh->incrRef();
11791       _nb_cell=mesh->getNumberOfCells();
11792     }
11793 }
11794
11795 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11796 {
11797   if(_mesh)
11798     _mesh->decrRef();
11799   if(_own_cell)
11800     delete _cell;
11801 }
11802
11803 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11804     _own_cell(false),_cell_id(bg-1),
11805     _nb_cell(end)
11806 {
11807   if(mesh)
11808     mesh->incrRef();
11809 }
11810
11811 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11812 {
11813   _cell_id++;
11814   if(_cell_id<_nb_cell)
11815     {
11816       _cell->next();
11817       return _cell;
11818     }
11819   else
11820     return 0;
11821 }
11822
11823 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11824 {
11825   if(_mesh)
11826     _mesh->incrRef();
11827 }
11828
11829 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11830 {
11831   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11832 }
11833
11834 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11835 {
11836   if(_mesh)
11837     _mesh->decrRef();
11838 }
11839
11840 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11841     _itc(itc),
11842     _bg(bg),_end(end)
11843 {
11844   if(_mesh)
11845     _mesh->incrRef();
11846 }
11847
11848 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11849 {
11850   if(_mesh)
11851     _mesh->decrRef();
11852 }
11853
11854 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11855 {
11856   return _type;
11857 }
11858
11859 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11860 {
11861   return _end-_bg;
11862 }
11863
11864 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11865 {
11866   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11867 }
11868
11869 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11870 {
11871   if(mesh)
11872     {
11873       mesh->incrRef();
11874       _nb_cell=mesh->getNumberOfCells();
11875     }
11876 }
11877
11878 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11879 {
11880   if(_mesh)
11881     _mesh->decrRef();
11882   delete _cell;
11883 }
11884
11885 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11886 {
11887   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11888   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11889   if(_cell_id<_nb_cell)
11890     {
11891       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11892       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
11893       int startId=_cell_id;
11894       _cell_id+=nbOfElems;
11895       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11896     }
11897   else
11898     return 0;
11899 }
11900
11901 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11902 {
11903   if(mesh)
11904     {
11905       _conn=mesh->getNodalConnectivity()->getPointer();
11906       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11907     }
11908 }
11909
11910 void MEDCouplingUMeshCell::next()
11911 {
11912   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11913     {
11914       _conn+=_conn_lgth;
11915       _conn_indx++;
11916     }
11917   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11918 }
11919
11920 std::string MEDCouplingUMeshCell::repr() const
11921 {
11922   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11923     {
11924       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11925       oss << " : ";
11926       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11927       return oss.str();
11928     }
11929   else
11930     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11931 }
11932
11933 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11934 {
11935   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11936     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11937   else
11938     return INTERP_KERNEL::NORM_ERROR;
11939 }
11940
11941 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11942 {
11943   lgth=_conn_lgth;
11944   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11945     return _conn;
11946   else
11947     return 0;
11948 }