Salome HOME
7ba64d25a7c1570b123a86ec30ebf91d36067784
[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 ParaMEDMEM;
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::deepCpy() 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::deepCpy 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::deepCpy
103  */
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCpyConnectivityOnly() const
105 {
106   checkConnectivityFullyDefined();
107   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
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::checkCoherency() const
169 {
170   if(_mesh_dim<-1)
171     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172   if(_mesh_dim!=-1)
173     MEDCouplingPointSet::checkCoherency();
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 checkCoherency(), 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::checkCoherency1(double eps) const
222 {
223   checkCoherency();
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::checkCoherency1 : 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::checkCoherency1 : 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::checkCoherency1 : 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 /*!
287  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
288  * then \a this mesh is most probably is writable, exchangeable and available for all
289  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
290  *  \param [in] eps - a not used parameter.
291  *  \throw If the mesh dimension is not set.
292  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
293  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
294  *  \throw If the connectivity data array has more than one component.
295  *  \throw If the connectivity data array has a named component.
296  *  \throw If the connectivity index data array has more than one component.
297  *  \throw If the connectivity index data array has a named component.
298  *  \throw If number of nodes defining an element does not correspond to the type of element.
299  *  \throw If the nodal connectivity includes an invalid node id.
300  */
301 void MEDCouplingUMesh::checkCoherency2(double eps) const
302 {
303   checkCoherency1(eps);
304 }
305
306 /*!
307  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
308  * elements contained in the mesh. For more info on the mesh dimension see
309  * \ref MEDCouplingUMeshPage.
310  *  \param [in] meshDim - a new mesh dimension.
311  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
312  */
313 void MEDCouplingUMesh::setMeshDimension(int meshDim)
314 {
315   if(meshDim<-1 || meshDim>3)
316     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
317   _mesh_dim=meshDim;
318   declareAsNew();
319 }
320
321 /*!
322  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
323  * 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.
324  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
325  *
326  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
327  *
328  *  \if ENABLE_EXAMPLES
329  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
330  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
331  *  \endif
332  */
333 void MEDCouplingUMesh::allocateCells(int nbOfCells)
334 {
335   if(nbOfCells<0)
336     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
337   if(_nodal_connec_index)
338     {
339       _nodal_connec_index->decrRef();
340     }
341   if(_nodal_connec)
342     {
343       _nodal_connec->decrRef();
344     }
345   _nodal_connec_index=DataArrayInt::New();
346   _nodal_connec_index->reserve(nbOfCells+1);
347   _nodal_connec_index->pushBackSilent(0);
348   _nodal_connec=DataArrayInt::New();
349   _nodal_connec->reserve(2*nbOfCells);
350   _types.clear();
351   declareAsNew();
352 }
353
354 /*!
355  * Appends a cell to the connectivity array. For deeper understanding what is
356  * happening see \ref MEDCouplingUMeshNodalConnectivity.
357  *  \param [in] type - type of cell to add.
358  *  \param [in] size - number of nodes constituting this cell.
359  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
360  * 
361  *  \if ENABLE_EXAMPLES
362  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
364  *  \endif
365  */
366 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
367 {
368   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
369   if(_nodal_connec_index==0)
370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
371   if((int)cm.getDimension()==_mesh_dim)
372     {
373       if(!cm.isDynamic())
374         if(size!=(int)cm.getNumberOfNodes())
375           {
376             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
377             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
378             throw INTERP_KERNEL::Exception(oss.str().c_str());
379           }
380       int idx=_nodal_connec_index->back();
381       int val=idx+size+1;
382       _nodal_connec_index->pushBackSilent(val);
383       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
384       _types.insert(type);
385     }
386   else
387     {
388       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
389       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
390       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
391       throw INTERP_KERNEL::Exception(oss.str().c_str());
392     }
393 }
394
395 /*!
396  * Compacts data arrays to release unused memory. This method is to be called after
397  * finishing cell insertion using \a this->insertNextCell().
398  * 
399  *  \if ENABLE_EXAMPLES
400  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
401  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
402  *  \endif
403  */
404 void MEDCouplingUMesh::finishInsertingCells()
405 {
406   _nodal_connec->pack();
407   _nodal_connec_index->pack();
408   _nodal_connec->declareAsNew();
409   _nodal_connec_index->declareAsNew();
410   updateTime();
411 }
412
413 /*!
414  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
415  * Useful for python users.
416  */
417 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
418 {
419   return new MEDCouplingUMeshCellIterator(this);
420 }
421
422 /*!
423  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
424  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
425  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
426  * Useful for python users.
427  */
428 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
429 {
430   if(!checkConsecutiveCellTypes())
431     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
432   return new MEDCouplingUMeshCellByTypeEntry(this);
433 }
434
435 /*!
436  * Returns a set of all cell types available in \a this mesh.
437  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
438  * \warning this method does not throw any exception even if \a this is not defined.
439  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
440  */
441 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
442 {
443   return _types;
444 }
445
446 /*!
447  * This method returns the sorted list of geometric types in \a this.
448  * 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
449  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
450  *
451  * \throw if connectivity in \a this is not correctly defined.
452  *  
453  * \sa MEDCouplingMesh::getAllGeoTypes
454  */
455 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
456 {
457   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
458   checkConnectivityFullyDefined();
459   int nbOfCells(getNumberOfCells());
460   if(nbOfCells==0)
461     return ret;
462   if(getMeshLength()<1)
463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
464   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
465   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
466   for(int i=1;i<nbOfCells;i++,ci++)
467     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
468       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
469   return ret;
470 }
471
472 /*!
473  * This method is a method that compares \a this and \a other.
474  * This method compares \b all attributes, even names and component names.
475  */
476 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
477 {
478   if(!other)
479     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
480   std::ostringstream oss; oss.precision(15);
481   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
482   if(!otherC)
483     {
484       reason="mesh given in input is not castable in MEDCouplingUMesh !";
485       return false;
486     }
487   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
488     return false;
489   if(_mesh_dim!=otherC->_mesh_dim)
490     {
491       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
492       reason=oss.str();
493       return false;
494     }
495   if(_types!=otherC->_types)
496     {
497       oss << "umesh geometric type mismatch :\nThis geometric types are :";
498       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
499         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500       oss << "\nOther geometric types are :";
501       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
502         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
503       reason=oss.str();
504       return false;
505     }
506   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
507     if(_nodal_connec==0 || otherC->_nodal_connec==0)
508       {
509         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
510         return false;
511       }
512   if(_nodal_connec!=otherC->_nodal_connec)
513     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
514       {
515         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
516         return false;
517       }
518   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
519     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
520       {
521         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
522         return false;
523       }
524   if(_nodal_connec_index!=otherC->_nodal_connec_index)
525     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
526       {
527         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
528         return false;
529       }
530   return true;
531 }
532
533 /*!
534  * Checks if data arrays of this mesh (node coordinates, nodal
535  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
536  * not considered.
537  *  \param [in] other - the mesh to compare with.
538  *  \param [in] prec - precision value used to compare node coordinates.
539  *  \return bool - \a true if the two meshes are same.
540  */
541 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
542 {
543   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
544   if(!otherC)
545     return false;
546   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
547     return false;
548   if(_mesh_dim!=otherC->_mesh_dim)
549     return false;
550   if(_types!=otherC->_types)
551     return false;
552   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
553     if(_nodal_connec==0 || otherC->_nodal_connec==0)
554       return false;
555   if(_nodal_connec!=otherC->_nodal_connec)
556     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
557       return false;
558   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
559     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
560       return false;
561   if(_nodal_connec_index!=otherC->_nodal_connec_index)
562     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
563       return false;
564   return true;
565 }
566
567 /*!
568  * Checks if \a this and \a other meshes are geometrically equivalent with high
569  * probability, else an exception is thrown. The meshes are considered equivalent if
570  * (1) meshes contain the same number of nodes and the same number of elements of the
571  * same types (2) three cells of the two meshes (first, last and middle) are based
572  * on coincident nodes (with a specified precision).
573  *  \param [in] other - the mesh to compare with.
574  *  \param [in] prec - the precision used to compare nodes of the two meshes.
575  *  \throw If the two meshes do not match.
576  */
577 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
578 {
579   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
580   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
581   if(!otherC)
582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
583 }
584
585 /*!
586  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
587  * cells each node belongs to.
588  * \warning For speed reasons, this method does not check if node ids in the nodal
589  *          connectivity correspond to the size of node coordinates array.
590  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
591  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
592  *        dividing cell ids in \a revNodal into groups each referring to one
593  *        node. Its every element (except the last one) is an index pointing to the
594  *         first id of a group of cells. For example cells sharing the node #1 are 
595  *        described by following range of indices: 
596  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
597  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
598  *        Number of cells sharing the *i*-th node is
599  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
600  * \throw If the coordinates array is not set.
601  * \throw If the nodal connectivity of cells is not defined.
602  * 
603  * \if ENABLE_EXAMPLES
604  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
605  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
606  * \endif
607  */
608 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
609 {
610   checkFullyDefined();
611   int nbOfNodes=getNumberOfNodes();
612   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
613   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
614   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
615   const int *conn=_nodal_connec->getConstPointer();
616   const int *connIndex=_nodal_connec_index->getConstPointer();
617   int nbOfCells=getNumberOfCells();
618   int nbOfEltsInRevNodal=0;
619   for(int eltId=0;eltId<nbOfCells;eltId++)
620     {
621       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
622       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
623       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
624         if(*iter>=0)//for polyhedrons
625           {
626             nbOfEltsInRevNodal++;
627             revNodalIndxPtr[(*iter)+1]++;
628           }
629     }
630   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
631   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
632   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
633   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
634   for(int eltId=0;eltId<nbOfCells;eltId++)
635     {
636       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
637       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
638       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
639         if(*iter>=0)//for polyhedrons
640           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
641     }
642 }
643
644 /// @cond INTERNAL
645
646 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
647 {
648   return id;
649 }
650
651 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
652 {
653   if(!compute)
654     return id+1;
655   else
656     {
657       if(cm.getOrientationStatus(nb,conn1,conn2))
658         return id+1;
659       else
660         return -(id+1);
661     }
662 }
663
664 class MinusOneSonsGenerator
665 {
666 public:
667   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670   static const int DELTA=1;
671 private:
672   const INTERP_KERNEL::CellModel& _cm;
673 };
674
675 class MinusOneSonsGeneratorBiQuadratic
676 {
677 public:
678   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
680   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681   static const int DELTA=1;
682 private:
683   const INTERP_KERNEL::CellModel& _cm;
684 };
685
686 class MinusTwoSonsGenerator
687 {
688 public:
689   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
690   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
691   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
692   static const int DELTA=2;
693 private:
694   const INTERP_KERNEL::CellModel& _cm;
695 };
696
697 /// @endcond
698
699 /*!
700  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
701  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
702  * describing correspondence between cells of \a this and the result meshes are
703  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
704  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
705  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
706  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
707  * \warning For speed reasons, this method does not check if node ids in the nodal
708  *          connectivity correspond to the size of node coordinates array.
709  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710  *          to write this mesh to the MED file, its cells must be sorted using
711  *          sortCellsInMEDFileFrmt().
712  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
713  *         each cell of \a this mesh.
714  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715  *        dividing cell ids in \a desc into groups each referring to one
716  *        cell of \a this mesh. Its every element (except the last one) is an index
717  *        pointing to the first id of a group of cells. For example cells of the
718  *        result mesh bounding the cell #1 of \a this mesh are described by following
719  *        range of indices:
720  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725  *         by each cell of the result mesh.
726  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
727  *        in the result mesh,
728  *        dividing cell ids in \a revDesc into groups each referring to one
729  *        cell of the result mesh the same way as \a descIndx divides \a desc.
730  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
731  *        delete this mesh using decrRef() as it is no more needed.
732  *  \throw If the coordinates array is not set.
733  *  \throw If the nodal connectivity of cells is node defined.
734  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
735  *         revDescIndx == NULL.
736  * 
737  *  \if ENABLE_EXAMPLES
738  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
739  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
740  *  \endif
741  * \sa buildDescendingConnectivity2()
742  */
743 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
744 {
745   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
746 }
747
748 /*!
749  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
750  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
751  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
752  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
753  * \sa MEDCouplingUMesh::buildDescendingConnectivity
754  */
755 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
756 {
757   checkFullyDefined();
758   if(getMeshDimension()!=3)
759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
760   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
761 }
762
763 /*!
764  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
765  * this->getMeshDimension(), that bound cells of \a this mesh. In
766  * addition arrays describing correspondence between cells of \a this and the result
767  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
768  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
769  *  mesh. This method differs from buildDescendingConnectivity() in that apart
770  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
771  * result meshes. So a positive id means that order of nodes in corresponding cells
772  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
773  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
774  * i.e. cell ids are one-based.
775  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
776  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
777  * \warning For speed reasons, this method does not check if node ids in the nodal
778  *          connectivity correspond to the size of node coordinates array.
779  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
780  *          to write this mesh to the MED file, its cells must be sorted using
781  *          sortCellsInMEDFileFrmt().
782  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
783  *         each cell of \a this mesh.
784  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
785  *        dividing cell ids in \a desc into groups each referring to one
786  *        cell of \a this mesh. Its every element (except the last one) is an index
787  *        pointing to the first id of a group of cells. For example cells of the
788  *        result mesh bounding the cell #1 of \a this mesh are described by following
789  *        range of indices:
790  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
791  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
792  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
793  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
794  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
795  *         by each cell of the result mesh.
796  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
797  *        in the result mesh,
798  *        dividing cell ids in \a revDesc into groups each referring to one
799  *        cell of the result mesh the same way as \a descIndx divides \a desc.
800  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
801  *        shares the node coordinates array with \a this mesh. The caller is to
802  *        delete this mesh using decrRef() as it is no more needed.
803  *  \throw If the coordinates array is not set.
804  *  \throw If the nodal connectivity of cells is node defined.
805  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
806  *         revDescIndx == NULL.
807  * 
808  *  \if ENABLE_EXAMPLES
809  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
810  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
811  *  \endif
812  * \sa buildDescendingConnectivity()
813  */
814 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
815 {
816   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
817 }
818
819 /*!
820  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
821  * For speed reasons no check of this will be done. This method calls
822  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
823  * This method lists cell by cell in \b this which are its neighbors. To compute the result
824  * only connectivities are considered.
825  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
826  * The format of return is hence \ref numbering-indirect.
827  *
828  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
829  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
830  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
831  * is equal to the last values in \b neighborsIndx.
832  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
833  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
834  */
835 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
836 {
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
841   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
842   meshDM1=0;
843   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
844 }
845
846 /*!
847  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
848  * of MEDCouplingUMesh::computeNeighborsOfCells.
849  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
850  * typically the case to extract a set a neighbours,
851  * excluding a set of meshdim-1 cells in input descending connectivity.
852  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
853  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
854  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
855  * are considered.
856  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
857  *
858  * \param [in] desc descending connectivity array.
859  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
860  * \param [in] revDesc reverse descending connectivity array.
861  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
862  * \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
863  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
864  * \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.
865  */
866 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
867                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
868 {
869   if(!desc || !descIndx || !revDesc || !revDescIndx)
870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
871   const int *descPtr=desc->getConstPointer();
872   const int *descIPtr=descIndx->getConstPointer();
873   const int *revDescPtr=revDesc->getConstPointer();
874   const int *revDescIPtr=revDescIndx->getConstPointer();
875   //
876   int nbCells=descIndx->getNumberOfTuples()-1;
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
879   int *out1Ptr=out1->getPointer();
880   *out1Ptr++=0;
881   out0->reserve(desc->getNumberOfTuples());
882   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
883     {
884       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
885         {
886           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
887           s.erase(i);
888           out0->insertAtTheEnd(s.begin(),s.end());
889         }
890       *out1Ptr=out0->getNumberOfTuples();
891     }
892   neighbors=out0.retn();
893   neighborsIndx=out1.retn();
894 }
895
896 /*!
897  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
898  * For speed reasons no check of this will be done. This method calls
899  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
900  * This method lists node by node in \b this which are its neighbors. To compute the result
901  * only connectivities are considered.
902  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
903  *
904  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
905  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
906  * parameter allows to select the right part in this array (\ref numbering-indirect).
907  * The number of tuples is equal to the last values in \b neighborsIndx.
908  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
909  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
910  */
911 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
912 {
913   checkFullyDefined();
914   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
917   switch(mdim)
918   {
919     case 3:
920       {
921         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
922         break;
923       }
924     case 2:
925       {
926         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
927         break;
928       }
929     case 1:
930       {
931         mesh1D=const_cast<MEDCouplingUMesh *>(this);
932         mesh1D->incrRef();
933         break;
934       }
935     default:
936       {
937         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
938       }
939   }
940   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
941   mesh1D->getReverseNodalConnectivity(desc,descIndx);
942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
943   ret0->alloc(desc->getNumberOfTuples(),1);
944   int *r0Pt(ret0->getPointer());
945   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
946   for(int i=0;i<nbNodes;i++,rni++)
947     {
948       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
949         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
950     }
951   neighbors=ret0.retn();
952   neighborsIdx=descIndx.retn();
953 }
954
955 /// @cond INTERNAL
956
957 /*!
958  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
959  * For speed reasons no check of this will be done.
960  */
961 template<class SonsGenerator>
962 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
963 {
964   if(!desc || !descIndx || !revDesc || !revDescIndx)
965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
966   checkConnectivityFullyDefined();
967   int nbOfCells=getNumberOfCells();
968   int nbOfNodes=getNumberOfNodes();
969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
970   int *revNodalIndxPtr=revNodalIndx->getPointer();
971   const int *conn=_nodal_connec->getConstPointer();
972   const int *connIndex=_nodal_connec_index->getConstPointer();
973   std::string name="Mesh constituent of "; name+=getName();
974   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
975   ret->setCoords(getCoords());
976   ret->allocateCells(2*nbOfCells);
977   descIndx->alloc(nbOfCells+1,1);
978   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
979   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
980   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
981     {
982       int pos=connIndex[eltId];
983       int posP1=connIndex[eltId+1];
984       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
985       SonsGenerator sg(cm);
986       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
987       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
988       for(unsigned i=0;i<nbOfSons;i++)
989         {
990           INTERP_KERNEL::NormalizedCellType cmsId;
991           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
992           for(unsigned k=0;k<nbOfNodesSon;k++)
993             if(tmp[k]>=0)
994               revNodalIndxPtr[tmp[k]+1]++;
995           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
996           revDesc2->pushBackSilent(eltId);
997         }
998       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
999     }
1000   int nbOfCellsM1=ret->getNumberOfCells();
1001   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1003   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1004   int *revNodalPtr=revNodal->getPointer();
1005   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1006   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1007   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1008     {
1009       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1010       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1011       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1012         if(*iter>=0)//for polyhedrons
1013           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1014     }
1015   //
1016   DataArrayInt *commonCells=0,*commonCellsI=0;
1017   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1019   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1020   int newNbOfCellsM1=-1;
1021   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1022                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1023   std::vector<bool> isImpacted(nbOfCellsM1,false);
1024   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1025     for(int work2=work[0];work2!=work[1];work2++)
1026       isImpacted[commonCellsPtr[work2]]=true;
1027   const int *o2nM1Ptr=o2nM1->getConstPointer();
1028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1029   const int *n2oM1Ptr=n2oM1->getConstPointer();
1030   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1031   ret2->copyTinyInfoFrom(this);
1032   desc->alloc(descIndx->back(),1);
1033   int *descPtr=desc->getPointer();
1034   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1035   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1036     {
1037       if(!isImpacted[i])
1038         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1039       else
1040         {
1041           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1042             {
1043               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1044               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1045             }
1046           else
1047             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1048         }
1049     }
1050   revDesc->reserve(newNbOfCellsM1);
1051   revDescIndx->alloc(newNbOfCellsM1+1,1);
1052   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1053   const int *revDesc2Ptr=revDesc2->getConstPointer();
1054   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1055     {
1056       int oldCellIdM1=n2oM1Ptr[i];
1057       if(!isImpacted[oldCellIdM1])
1058         {
1059           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1060           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1061         }
1062       else
1063         {
1064           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1065             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1066           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1067           commonCellsIPtr++;
1068         }
1069     }
1070   //
1071   return ret2.retn();
1072 }
1073
1074 struct MEDCouplingAccVisit
1075 {
1076   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1077   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1078   int _new_nb_of_nodes;
1079 };
1080
1081 /// @endcond
1082
1083 /*!
1084  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1085  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1086  * array of cell ids. Pay attention that after conversion all algorithms work slower
1087  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1088  * conversion due presence of invalid ids in the array of cells to convert, as a
1089  * result \a this mesh contains some already converted elements. In this case the 2D
1090  * mesh remains valid but 3D mesh becomes \b inconsistent!
1091  *  \warning This method can significantly modify the order of geometric types in \a this,
1092  *          hence, to write this mesh to the MED file, its cells must be sorted using
1093  *          sortCellsInMEDFileFrmt().
1094  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1095  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1096  *         cellIdsToConvertBg.
1097  *  \throw If the coordinates array is not set.
1098  *  \throw If the nodal connectivity of cells is node defined.
1099  *  \throw If dimension of \a this mesh is not either 2 or 3.
1100  *
1101  *  \if ENABLE_EXAMPLES
1102  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1103  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1104  *  \endif
1105  */
1106 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1107 {
1108   checkFullyDefined();
1109   int dim=getMeshDimension();
1110   if(dim<2 || dim>3)
1111     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1112   int nbOfCells(getNumberOfCells());
1113   if(dim==2)
1114     {
1115       const int *connIndex=_nodal_connec_index->getConstPointer();
1116       int *conn=_nodal_connec->getPointer();
1117       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1118         {
1119           if(*iter>=0 && *iter<nbOfCells)
1120             {
1121               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1122               if(!cm.isQuadratic())
1123                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1124               else
1125                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1126             }
1127           else
1128             {
1129               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130               oss << " in range [0," << nbOfCells << ") !";
1131               throw INTERP_KERNEL::Exception(oss.str().c_str());
1132             }
1133         }
1134     }
1135   else
1136     {
1137       int *connIndex(_nodal_connec_index->getPointer());
1138       const int *connOld(_nodal_connec->getConstPointer());
1139       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1140       std::vector<bool> toBeDone(nbOfCells,false);
1141       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1142         {
1143           if(*iter>=0 && *iter<nbOfCells)
1144             toBeDone[*iter]=true;
1145           else
1146             {
1147               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1148               oss << " in range [0," << nbOfCells << ") !";
1149               throw INTERP_KERNEL::Exception(oss.str().c_str());
1150             }
1151         }
1152       for(int cellId=0;cellId<nbOfCells;cellId++)
1153         {
1154           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1155           int lgthOld(posP1-pos-1);
1156           if(toBeDone[cellId])
1157             {
1158               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1159               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1160               int *tmp(new int[nbOfFaces*lgthOld+1]);
1161               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1162               for(unsigned j=0;j<nbOfFaces;j++)
1163                 {
1164                   INTERP_KERNEL::NormalizedCellType type;
1165                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1166                   work+=offset;
1167                   *work++=-1;
1168                 }
1169               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1170               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1171               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1172               delete [] tmp;
1173             }
1174           else
1175             {
1176               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1177               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1178             }
1179         }
1180       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1181     }
1182   computeTypes();
1183 }
1184
1185 /*!
1186  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1187  * polyhedrons (if \a this is a 3D mesh).
1188  *  \warning As this method is purely for user-friendliness and no optimization is
1189  *          done to avoid construction of a useless vector, this method can be costly
1190  *          in memory.
1191  *  \throw If the coordinates array is not set.
1192  *  \throw If the nodal connectivity of cells is node defined.
1193  *  \throw If dimension of \a this mesh is not either 2 or 3.
1194  */
1195 void MEDCouplingUMesh::convertAllToPoly()
1196 {
1197   int nbOfCells=getNumberOfCells();
1198   std::vector<int> cellIds(nbOfCells);
1199   for(int i=0;i<nbOfCells;i++)
1200     cellIds[i]=i;
1201   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1202 }
1203
1204 /*!
1205  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1206  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1207  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1208  * base facet of the volume and the second half of nodes describes an opposite facet
1209  * having the same number of nodes as the base one. This method converts such
1210  * connectivity to a valid polyhedral format where connectivity of each facet is
1211  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1212  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1213  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1214  * a correct orientation of the first facet of a polyhedron, else orientation of a
1215  * corrected cell is reverse.<br>
1216  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1217  * it releases the user from boring description of polyhedra connectivity in the valid
1218  * format.
1219  *  \throw If \a this->getMeshDimension() != 3.
1220  *  \throw If \a this->getSpaceDimension() != 3.
1221  *  \throw If the nodal connectivity of cells is not defined.
1222  *  \throw If the coordinates array is not set.
1223  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1224  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1225  *
1226  *  \if ENABLE_EXAMPLES
1227  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1228  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1229  *  \endif
1230  */
1231 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1232 {
1233   checkFullyDefined();
1234   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1235     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1236   int nbOfCells=getNumberOfCells();
1237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1238   newCi->alloc(nbOfCells+1,1);
1239   int *newci=newCi->getPointer();
1240   const int *ci=_nodal_connec_index->getConstPointer();
1241   const int *c=_nodal_connec->getConstPointer();
1242   newci[0]=0;
1243   for(int i=0;i<nbOfCells;i++)
1244     {
1245       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1246       if(type==INTERP_KERNEL::NORM_POLYHED)
1247         {
1248           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1249             {
1250               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1251               throw INTERP_KERNEL::Exception(oss.str().c_str());
1252             }
1253           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1254           if(n2%2!=0)
1255             {
1256               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 !";
1257               throw INTERP_KERNEL::Exception(oss.str().c_str());
1258             }
1259           int n1=(int)(n2/2);
1260           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)
1261         }
1262       else
1263         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1264     }
1265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1266   newC->alloc(newci[nbOfCells],1);
1267   int *newc=newC->getPointer();
1268   for(int i=0;i<nbOfCells;i++)
1269     {
1270       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1271       if(type==INTERP_KERNEL::NORM_POLYHED)
1272         {
1273           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1274           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1275           *newc++=-1;
1276           for(std::size_t j=0;j<n1;j++)
1277             {
1278               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1279               newc[n1+5*j]=-1;
1280               newc[n1+5*j+1]=c[ci[i]+1+j];
1281               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1282               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1283               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1284             }
1285           newc+=n1*6;
1286         }
1287       else
1288         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1289     }
1290   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1291   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1292 }
1293
1294
1295 /*!
1296  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1297  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1298  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1299  *          to write this mesh to the MED file, its cells must be sorted using
1300  *          sortCellsInMEDFileFrmt().
1301  * \return \c true if at least one cell has been converted, \c false else. In the
1302  *         last case the nodal connectivity remains unchanged.
1303  * \throw If the coordinates array is not set.
1304  * \throw If the nodal connectivity of cells is not defined.
1305  * \throw If \a this->getMeshDimension() < 0.
1306  */
1307 bool MEDCouplingUMesh::unPolyze()
1308 {
1309   checkFullyDefined();
1310   int mdim=getMeshDimension();
1311   if(mdim<0)
1312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1313   if(mdim<=1)
1314     return false;
1315   int nbOfCells=getNumberOfCells();
1316   if(nbOfCells<1)
1317     return false;
1318   int initMeshLgth=getMeshLength();
1319   int *conn=_nodal_connec->getPointer();
1320   int *index=_nodal_connec_index->getPointer();
1321   int posOfCurCell=0;
1322   int newPos=0;
1323   int lgthOfCurCell;
1324   bool ret=false;
1325   for(int i=0;i<nbOfCells;i++)
1326     {
1327       lgthOfCurCell=index[i+1]-posOfCurCell;
1328       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1329       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1330       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1331       int newLgth;
1332       if(cm.isDynamic())
1333         {
1334           switch(cm.getDimension())
1335           {
1336             case 2:
1337               {
1338                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1339                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1340                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1341                 break;
1342               }
1343             case 3:
1344               {
1345                 int nbOfFaces,lgthOfPolyhConn;
1346                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1347                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1348                 break;
1349               }
1350             case 1:
1351               {
1352                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1353                 break;
1354               }
1355           }
1356           ret=ret || (newType!=type);
1357           conn[newPos]=newType;
1358           newPos+=newLgth+1;
1359           posOfCurCell=index[i+1];
1360           index[i+1]=newPos;
1361         }
1362       else
1363         {
1364           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1365           newPos+=lgthOfCurCell;
1366           posOfCurCell+=lgthOfCurCell;
1367           index[i+1]=newPos;
1368         }
1369     }
1370   if(newPos!=initMeshLgth)
1371     _nodal_connec->reAlloc(newPos);
1372   if(ret)
1373     computeTypes();
1374   return ret;
1375 }
1376
1377 /*!
1378  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1379  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1380  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1381  *
1382  * \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 
1383  *             precision.
1384  */
1385 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1386 {
1387   checkFullyDefined();
1388   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1389     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1390   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1391   coords->recenterForMaxPrecision(eps);
1392   //
1393   int nbOfCells=getNumberOfCells();
1394   const int *conn=_nodal_connec->getConstPointer();
1395   const int *index=_nodal_connec_index->getConstPointer();
1396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1397   connINew->alloc(nbOfCells+1,1);
1398   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1400   bool changed=false;
1401   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1402     {
1403       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1404         {
1405           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1406           changed=true;
1407         }
1408       else
1409         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1410       *connINewPtr=connNew->getNumberOfTuples();
1411     }
1412   if(changed)
1413     setConnectivity(connNew,connINew,false);
1414 }
1415
1416 /*!
1417  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1418  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1419  * the format of the returned DataArrayInt instance.
1420  * 
1421  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1422  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1423  */
1424 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1425 {
1426   checkConnectivityFullyDefined();
1427   int nbOfCells=getNumberOfCells();
1428   const int *connIndex=_nodal_connec_index->getConstPointer();
1429   const int *conn=_nodal_connec->getConstPointer();
1430   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1431   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1432   std::vector<bool> retS(maxElt,false);
1433   for(int i=0;i<nbOfCells;i++)
1434     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1435       if(conn[j]>=0)
1436         retS[conn[j]]=true;
1437   int sz=0;
1438   for(int i=0;i<maxElt;i++)
1439     if(retS[i])
1440       sz++;
1441   DataArrayInt *ret=DataArrayInt::New();
1442   ret->alloc(sz,1);
1443   int *retPtr=ret->getPointer();
1444   for(int i=0;i<maxElt;i++)
1445     if(retS[i])
1446       *retPtr++=i;
1447   return ret;
1448 }
1449
1450 /*!
1451  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1452  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1453  */
1454 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1455 {
1456   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1457   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1458   for(int i=0;i<nbOfCells;i++)
1459     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1460       if(conn[j]>=0)
1461         {
1462           if(conn[j]<nbOfNodes)
1463             nodeIdsInUse[conn[j]]=true;
1464           else
1465             {
1466               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1467               throw INTERP_KERNEL::Exception(oss.str().c_str());
1468             }
1469         }
1470 }
1471
1472 /*!
1473  * Finds nodes not used in any cell and returns an array giving a new id to every node
1474  * by excluding the unused nodes, for which the array holds -1. The result array is
1475  * a mapping in "Old to New" mode. 
1476  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1477  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1478  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1479  *          if the node is unused or a new id else. The caller is to delete this
1480  *          array using decrRef() as it is no more needed.  
1481  *  \throw If the coordinates array is not set.
1482  *  \throw If the nodal connectivity of cells is not defined.
1483  *  \throw If the nodal connectivity includes an invalid id.
1484  *
1485  *  \if ENABLE_EXAMPLES
1486  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1487  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1488  *  \endif
1489  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1490  */
1491 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1492 {
1493   nbrOfNodesInUse=-1;
1494   int nbOfNodes(getNumberOfNodes());
1495   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1496   ret->alloc(nbOfNodes,1);
1497   int *traducer=ret->getPointer();
1498   std::fill(traducer,traducer+nbOfNodes,-1);
1499   int nbOfCells=getNumberOfCells();
1500   const int *connIndex=_nodal_connec_index->getConstPointer();
1501   const int *conn=_nodal_connec->getConstPointer();
1502   for(int i=0;i<nbOfCells;i++)
1503     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1504       if(conn[j]>=0)
1505         {
1506           if(conn[j]<nbOfNodes)
1507             traducer[conn[j]]=1;
1508           else
1509             {
1510               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1511               throw INTERP_KERNEL::Exception(oss.str().c_str());
1512             }
1513         }
1514   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1515   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1516   return ret.retn();
1517 }
1518
1519 /*!
1520  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1521  * For each cell in \b this the number of nodes constituting cell is computed.
1522  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1523  * So for pohyhedrons some nodes can be counted several times in the returned result.
1524  * 
1525  * \return a newly allocated array
1526  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1527  */
1528 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1529 {
1530   checkConnectivityFullyDefined();
1531   int nbOfCells=getNumberOfCells();
1532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1533   ret->alloc(nbOfCells,1);
1534   int *retPtr=ret->getPointer();
1535   const int *conn=getNodalConnectivity()->getConstPointer();
1536   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1537   for(int i=0;i<nbOfCells;i++,retPtr++)
1538     {
1539       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1540         *retPtr=connI[i+1]-connI[i]-1;
1541       else
1542         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1543     }
1544   return ret.retn();
1545 }
1546
1547 /*!
1548  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1549  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1550  *
1551  * \return DataArrayInt * - new object to be deallocated by the caller.
1552  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1553  */
1554 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1555 {
1556   checkConnectivityFullyDefined();
1557   int nbOfCells=getNumberOfCells();
1558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1559   ret->alloc(nbOfCells,1);
1560   int *retPtr=ret->getPointer();
1561   const int *conn=getNodalConnectivity()->getConstPointer();
1562   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1563   for(int i=0;i<nbOfCells;i++,retPtr++)
1564     {
1565       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1566       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1567         *retPtr=(int)s.size();
1568       else
1569         {
1570           s.erase(-1);
1571           *retPtr=(int)s.size();
1572         }
1573     }
1574   return ret.retn();
1575 }
1576
1577 /*!
1578  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1579  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1580  * 
1581  * \return a newly allocated array
1582  */
1583 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1584 {
1585   checkConnectivityFullyDefined();
1586   int nbOfCells=getNumberOfCells();
1587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1588   ret->alloc(nbOfCells,1);
1589   int *retPtr=ret->getPointer();
1590   const int *conn=getNodalConnectivity()->getConstPointer();
1591   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1592   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1593     {
1594       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1595       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1596     }
1597   return ret.retn();
1598 }
1599
1600 /*!
1601  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1602  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1603  * array mean that the corresponding old node is no more used. 
1604  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1605  *           this->getNumberOfNodes() before call of this method. The caller is to
1606  *           delete this array using decrRef() as it is no more needed. 
1607  *  \throw If the coordinates array is not set.
1608  *  \throw If the nodal connectivity of cells is not defined.
1609  *  \throw If the nodal connectivity includes an invalid id.
1610  *  \sa areAllNodesFetched
1611  *
1612  *  \if ENABLE_EXAMPLES
1613  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1614  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1615  *  \endif
1616  */
1617 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1618 {
1619   return MEDCouplingPointSet::zipCoordsTraducer();
1620 }
1621
1622 /*!
1623  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1624  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1625  */
1626 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1627 {
1628   switch(compType)
1629   {
1630     case 0:
1631       return AreCellsEqual0(conn,connI,cell1,cell2);
1632     case 1:
1633       return AreCellsEqual1(conn,connI,cell1,cell2);
1634     case 2:
1635       return AreCellsEqual2(conn,connI,cell1,cell2);
1636     case 3:
1637       return AreCellsEqual3(conn,connI,cell1,cell2);
1638     case 7:
1639       return AreCellsEqual7(conn,connI,cell1,cell2);
1640   }
1641   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1642 }
1643
1644 /*!
1645  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1646  */
1647 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1648 {
1649   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1650     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1651   return 0;
1652 }
1653
1654 /*!
1655  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1656  */
1657 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1658 {
1659   int sz=connI[cell1+1]-connI[cell1];
1660   if(sz==connI[cell2+1]-connI[cell2])
1661     {
1662       if(conn[connI[cell1]]==conn[connI[cell2]])
1663         {
1664           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1665           unsigned dim=cm.getDimension();
1666           if(dim!=3)
1667             {
1668               if(dim!=1)
1669                 {
1670                   int sz1=2*(sz-1);
1671                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1672                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1673                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1674                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1675                   return work!=tmp+sz1?1:0;
1676                 }
1677               else
1678                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1679             }
1680           else
1681             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1682         }
1683     }
1684   return 0;
1685 }
1686
1687 /*!
1688  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1689  */
1690 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1691 {
1692   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1693     {
1694       if(conn[connI[cell1]]==conn[connI[cell2]])
1695         {
1696           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1697           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1698           return s1==s2?1:0;
1699         }
1700     }
1701   return 0;
1702 }
1703
1704 /*!
1705  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1706  */
1707 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1708 {
1709   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1710     {
1711       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1712       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1713       return s1==s2?1:0;
1714     }
1715   return 0;
1716 }
1717
1718 /*!
1719  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1720  */
1721 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1722 {
1723   int sz=connI[cell1+1]-connI[cell1];
1724   if(sz==connI[cell2+1]-connI[cell2])
1725     {
1726       if(conn[connI[cell1]]==conn[connI[cell2]])
1727         {
1728           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1729           unsigned dim=cm.getDimension();
1730           if(dim!=3)
1731             {
1732               if(dim!=1)
1733                 {
1734                   int sz1=2*(sz-1);
1735                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1736                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1737                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1738                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1739                   if(work!=tmp+sz1)
1740                     return 1;
1741                   else
1742                     {
1743                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1744                       std::reverse_iterator<int *> it2((int *)tmp);
1745                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1746                         return 2;
1747                       else
1748                         return 0;
1749                     }
1750
1751                   return work!=tmp+sz1?1:0;
1752                 }
1753               else
1754                 {//case of SEG2 and SEG3
1755                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1756                     return 1;
1757                   if(!cm.isQuadratic())
1758                     {
1759                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1760                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1761                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1762                         return 2;
1763                       return 0;
1764                     }
1765                   else
1766                     {
1767                       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])
1768                         return 2;
1769                       return 0;
1770                     }
1771                 }
1772             }
1773           else
1774             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1775         }
1776     }
1777   return 0;
1778 }
1779
1780 /*!
1781  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1782  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1783  * and result remains unchanged.
1784  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1785  * If in 'candidates' pool -1 value is considered as an empty value.
1786  * WARNING this method returns only ONE set of result !
1787  */
1788 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1789 {
1790   if(candidates.size()<1)
1791     return false;
1792   bool ret=false;
1793   std::vector<int>::const_iterator iter=candidates.begin();
1794   int start=(*iter++);
1795   for(;iter!=candidates.end();iter++)
1796     {
1797       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1798       if(status!=0)
1799         {
1800           if(!ret)
1801             {
1802               result->pushBackSilent(start);
1803               ret=true;
1804             }
1805           if(status==1)
1806             result->pushBackSilent(*iter);
1807           else
1808             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1809         }
1810     }
1811   return ret;
1812 }
1813
1814 /*!
1815  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1816  * by \a compType.
1817  * This method keeps the coordiantes of \a this. This method is time consuming.
1818  *
1819  * \param [in] compType input specifying the technique used to compare cells each other.
1820  *   - 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.
1821  *   - 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)
1822  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1823  *   - 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
1824  * can be used for users not sensitive to orientation of cell
1825  * \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.
1826  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1827  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1828  * \return the correspondance array old to new in a newly allocated array.
1829  * 
1830  */
1831 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1832 {
1833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1834   getReverseNodalConnectivity(revNodal,revNodalI);
1835   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1836 }
1837
1838 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1839                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1840 {
1841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1842   int nbOfCells=nodalI->getNumberOfTuples()-1;
1843   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1844   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1845   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1846   std::vector<bool> isFetched(nbOfCells,false);
1847   if(startCellId==0)
1848     {
1849       for(int i=0;i<nbOfCells;i++)
1850         {
1851           if(!isFetched[i])
1852             {
1853               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1854               std::vector<int> v,v2;
1855               if(connOfNode!=connPtr+connIPtr[i+1])
1856                 {
1857                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1858                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1859                   connOfNode++;
1860                 }
1861               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1862                 if(*connOfNode>=0)
1863                   {
1864                     v=v2;
1865                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1866                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1867                     v2.resize(std::distance(v2.begin(),it));
1868                   }
1869               if(v2.size()>1)
1870                 {
1871                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1872                     {
1873                       int pos=commonCellsI->back();
1874                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1875                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1876                         isFetched[*it]=true;
1877                     }
1878                 }
1879             }
1880         }
1881     }
1882   else
1883     {
1884       for(int i=startCellId;i<nbOfCells;i++)
1885         {
1886           if(!isFetched[i])
1887             {
1888               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1889               std::vector<int> v,v2;
1890               if(connOfNode!=connPtr+connIPtr[i+1])
1891                 {
1892                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1893                   connOfNode++;
1894                 }
1895               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1896                 if(*connOfNode>=0)
1897                   {
1898                     v=v2;
1899                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1900                     v2.resize(std::distance(v2.begin(),it));
1901                   }
1902               if(v2.size()>1)
1903                 {
1904                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1905                     {
1906                       int pos=commonCellsI->back();
1907                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1908                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1909                         isFetched[*it]=true;
1910                     }
1911                 }
1912             }
1913         }
1914     }
1915   commonCellsArr=commonCells.retn();
1916   commonCellsIArr=commonCellsI.retn();
1917 }
1918
1919 /*!
1920  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1921  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1922  * than \a other->getNumberOfCells() in the returned array means that there is no
1923  * corresponding cell in \a this mesh.
1924  * It is expected that \a this and \a other meshes share the same node coordinates
1925  * array, if it is not so an exception is thrown. 
1926  *  \param [in] other - the mesh to compare with.
1927  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1928  *         valid values [0,1,2], see zipConnectivityTraducer().
1929  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1930  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1931  *         values. The caller is to delete this array using
1932  *         decrRef() as it is no more needed.
1933  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1934  *         mesh.
1935  *
1936  *  \if ENABLE_EXAMPLES
1937  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1938  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1939  *  \endif
1940  *  \sa checkDeepEquivalOnSameNodesWith()
1941  *  \sa checkGeoEquivalWith()
1942  */
1943 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1944 {
1945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1946   int nbOfCells=getNumberOfCells();
1947   static const int possibleCompType[]={0,1,2};
1948   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1949     {
1950       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1951       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1952       oss << " !";
1953       throw INTERP_KERNEL::Exception(oss.str().c_str());
1954     }
1955   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1956   arr=o2n->substr(nbOfCells);
1957   arr->setName(other->getName());
1958   int tmp;
1959   if(other->getNumberOfCells()==0)
1960     return true;
1961   return arr->getMaxValue(tmp)<nbOfCells;
1962 }
1963
1964 /*!
1965  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1966  * This method tries to determine if \b other is fully included in \b this.
1967  * The main difference is that this method is not expected to throw exception.
1968  * This method has two outputs :
1969  *
1970  * \param other other mesh
1971  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1972  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1973  */
1974 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1975 {
1976   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1977   DataArrayInt *commonCells=0,*commonCellsI=0;
1978   int thisNbCells=getNumberOfCells();
1979   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1981   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1982   int otherNbCells=other->getNumberOfCells();
1983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1984   arr2->alloc(otherNbCells,1);
1985   arr2->fillWithZero();
1986   int *arr2Ptr=arr2->getPointer();
1987   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1988   for(int i=0;i<nbOfCommon;i++)
1989     {
1990       int start=commonCellsPtr[commonCellsIPtr[i]];
1991       if(start<thisNbCells)
1992         {
1993           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1994             {
1995               int sig=commonCellsPtr[j]>0?1:-1;
1996               int val=std::abs(commonCellsPtr[j])-1;
1997               if(val>=thisNbCells)
1998                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1999             }
2000         }
2001     }
2002   arr2->setName(other->getName());
2003   if(arr2->presenceOfValue(0))
2004     return false;
2005   arr=arr2.retn();
2006   return true;
2007 }
2008
2009 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2010 {
2011   if(!other)
2012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2013   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2014   if(!otherC)
2015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2016   std::vector<const MEDCouplingUMesh *> ms(2);
2017   ms[0]=this;
2018   ms[1]=otherC;
2019   return MergeUMeshesOnSameCoords(ms);
2020 }
2021
2022 /*!
2023  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2024  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2025  * cellIds is not given explicitely but by a range python like.
2026  * 
2027  * \param start
2028  * \param end
2029  * \param step
2030  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2031  * \return a newly allocated
2032  * 
2033  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2034  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2035  */
2036 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2037 {
2038   if(getMeshDimension()!=-1)
2039     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords));
2040   else
2041     {
2042       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2043       if(newNbOfCells!=1)
2044         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2045       if(start!=0)
2046         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2047       incrRef();
2048       return const_cast<MEDCouplingUMesh *>(this);
2049     }
2050 }
2051
2052 /*!
2053  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2054  * The result mesh shares or not the node coordinates array with \a this mesh depending
2055  * on \a keepCoords parameter.
2056  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2057  *           to write this mesh to the MED file, its cells must be sorted using
2058  *           sortCellsInMEDFileFrmt().
2059  *  \param [in] begin - an array of cell ids to include to the new mesh.
2060  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2061  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2062  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2063  *         by calling zipCoords().
2064  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2065  *         to delete this mesh using decrRef() as it is no more needed. 
2066  *  \throw If the coordinates array is not set.
2067  *  \throw If the nodal connectivity of cells is not defined.
2068  *  \throw If any cell id in the array \a begin is not valid.
2069  *
2070  *  \if ENABLE_EXAMPLES
2071  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2072  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2073  *  \endif
2074  */
2075 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2076 {
2077   if(getMeshDimension()!=-1)
2078     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2079   else
2080     {
2081       if(end-begin!=1)
2082         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2083       if(begin[0]!=0)
2084         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2085       incrRef();
2086       return const_cast<MEDCouplingUMesh *>(this);
2087     }
2088 }
2089
2090 /*!
2091  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2092  *
2093  * 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.
2094  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2095  * The number of cells of \b this will remain the same with this method.
2096  *
2097  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2098  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2099  * \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 ).
2100  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2101  */
2102 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2103 {
2104   checkConnectivityFullyDefined();
2105   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2106   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2108   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2109     {
2110       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2111       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2112       throw INTERP_KERNEL::Exception(oss.str().c_str());
2113     }
2114   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2115   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2116     {
2117       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2118       throw INTERP_KERNEL::Exception(oss.str().c_str());
2119     }
2120   int nbOfCells=getNumberOfCells();
2121   bool easyAssign=true;
2122   const int *connI=_nodal_connec_index->getConstPointer();
2123   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2124   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2125     {
2126       if(*it>=0 && *it<nbOfCells)
2127         {
2128           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2129         }
2130       else
2131         {
2132           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2133           throw INTERP_KERNEL::Exception(oss.str().c_str());
2134         }
2135     }
2136   if(easyAssign)
2137     {
2138       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2139       computeTypes();
2140     }
2141   else
2142     {
2143       DataArrayInt *arrOut=0,*arrIOut=0;
2144       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2145                                                arrOut,arrIOut);
2146       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2147       setConnectivity(arrOut,arrIOut,true);
2148     }
2149 }
2150
2151 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2152 {
2153   checkConnectivityFullyDefined();
2154   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2155   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2157   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2158     {
2159       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2160       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2161       throw INTERP_KERNEL::Exception(oss.str().c_str());
2162     }
2163   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2164   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2165     {
2166       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2167       throw INTERP_KERNEL::Exception(oss.str().c_str());
2168     }
2169   int nbOfCells=getNumberOfCells();
2170   bool easyAssign=true;
2171   const int *connI=_nodal_connec_index->getConstPointer();
2172   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2173   int it=start;
2174   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2175     {
2176       if(it>=0 && it<nbOfCells)
2177         {
2178           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2179         }
2180       else
2181         {
2182           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2183           throw INTERP_KERNEL::Exception(oss.str().c_str());
2184         }
2185     }
2186   if(easyAssign)
2187     {
2188       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2189       computeTypes();
2190     }
2191   else
2192     {
2193       DataArrayInt *arrOut=0,*arrIOut=0;
2194       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2195                                                 arrOut,arrIOut);
2196       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2197       setConnectivity(arrOut,arrIOut,true);
2198     }
2199 }                      
2200
2201 /*!
2202  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2203  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2204  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2205  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2206  *
2207  * \param [in] begin input start of array of node ids.
2208  * \param [in] end input end of array of node ids.
2209  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2210  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2211  */
2212 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2213 {
2214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2215   checkConnectivityFullyDefined();
2216   int tmp=-1;
2217   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2218   std::vector<bool> fastFinder(sz,false);
2219   for(const int *work=begin;work!=end;work++)
2220     if(*work>=0 && *work<sz)
2221       fastFinder[*work]=true;
2222   int nbOfCells=getNumberOfCells();
2223   const int *conn=getNodalConnectivity()->getConstPointer();
2224   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2225   for(int i=0;i<nbOfCells;i++)
2226     {
2227       int ref=0,nbOfHit=0;
2228       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2229         if(*work2>=0)
2230           {
2231             ref++;
2232             if(fastFinder[*work2])
2233               nbOfHit++;
2234           }
2235       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2236         cellIdsKept->pushBackSilent(i);
2237     }
2238   cellIdsKeptArr=cellIdsKept.retn();
2239 }
2240
2241 /*!
2242  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2243  * this->getMeshDimension(), that bound some cells of \a this mesh.
2244  * The cells of lower dimension to include to the result mesh are selected basing on
2245  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2246  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2247  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2248  * created mesh shares the node coordinates array with \a this mesh. 
2249  *  \param [in] begin - the array of node ids.
2250  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2251  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2252  *         array \a begin are added, else cells whose any node is in the
2253  *         array \a begin are added.
2254  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2255  *         to delete this mesh using decrRef() as it is no more needed. 
2256  *  \throw If the coordinates array is not set.
2257  *  \throw If the nodal connectivity of cells is not defined.
2258  *  \throw If any node id in \a begin is not valid.
2259  *
2260  *  \if ENABLE_EXAMPLES
2261  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2262  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2263  *  \endif
2264  */
2265 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2266 {
2267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2268   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2270   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2271   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2272 }
2273
2274 /*!
2275  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2276  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2277  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2278  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2279  *         by calling zipCoords().
2280  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2281  *         to delete this mesh using decrRef() as it is no more needed. 
2282  *  \throw If the coordinates array is not set.
2283  *  \throw If the nodal connectivity of cells is not defined.
2284  *
2285  *  \if ENABLE_EXAMPLES
2286  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2287  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2288  *  \endif
2289  */
2290 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2291 {
2292   DataArrayInt *desc=DataArrayInt::New();
2293   DataArrayInt *descIndx=DataArrayInt::New();
2294   DataArrayInt *revDesc=DataArrayInt::New();
2295   DataArrayInt *revDescIndx=DataArrayInt::New();
2296   //
2297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2298   revDesc->decrRef();
2299   desc->decrRef();
2300   descIndx->decrRef();
2301   int nbOfCells=meshDM1->getNumberOfCells();
2302   const int *revDescIndxC=revDescIndx->getConstPointer();
2303   std::vector<int> boundaryCells;
2304   for(int i=0;i<nbOfCells;i++)
2305     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2306       boundaryCells.push_back(i);
2307   revDescIndx->decrRef();
2308   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2309   return ret;
2310 }
2311
2312 /*!
2313  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2314  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2315  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2316  */
2317 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2318 {
2319   checkFullyDefined();
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2324   //
2325   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2326   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2327   //
2328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2330   const int *revDescPtr=revDesc->getConstPointer();
2331   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2332   int nbOfCells=getNumberOfCells();
2333   std::vector<bool> ret1(nbOfCells,false);
2334   int sz=0;
2335   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2336     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2337       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2338   //
2339   DataArrayInt *ret2=DataArrayInt::New();
2340   ret2->alloc(sz,1);
2341   int *ret2Ptr=ret2->getPointer();
2342   sz=0;
2343   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2344     if(*it)
2345       *ret2Ptr++=sz;
2346   ret2->setName("BoundaryCells");
2347   return ret2;
2348 }
2349
2350 /*!
2351  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2352  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2353  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2354  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2355  *
2356  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2357  * 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
2358  * equals a cell in \b otherDimM1OnSameCoords.
2359  *
2360  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2361  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2362  *
2363  * \param [in] otherDimM1OnSameCoords
2364  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2365  * \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
2366  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2367  */
2368 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2369 {
2370   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2372   checkConnectivityFullyDefined();
2373   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2374   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2375     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2378   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2380   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2381   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2382   DataArrayInt *idsOtherInConsti=0;
2383   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2385   if(!b)
2386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2387   std::set<int> s1;
2388   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2389     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2391   s1arr_renum1->sort();
2392   cellIdsRk0=s0arr.retn();
2393   //cellIdsRk1=s_renum1.retn();
2394   cellIdsRk1=s1arr_renum1.retn();
2395 }
2396
2397 /*!
2398  * 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
2399  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2400  * 
2401  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2402  */
2403 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2404 {
2405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2409   //
2410   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2411   revDesc=0; desc=0; descIndx=0;
2412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2414   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2415 }
2416
2417 /*!
2418  * Finds nodes lying on the boundary of \a this mesh.
2419  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2420  *          nodes. The caller is to delete this array using decrRef() as it is no
2421  *          more needed.
2422  *  \throw If the coordinates array is not set.
2423  *  \throw If the nodal connectivity of cells is node defined.
2424  *
2425  *  \if ENABLE_EXAMPLES
2426  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2427  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2428  *  \endif
2429  */
2430 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2431 {
2432   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2433   return skin->computeFetchedNodeIds();
2434 }
2435
2436 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2437 {
2438   incrRef();
2439   return const_cast<MEDCouplingUMesh *>(this);
2440 }
2441
2442 /*!
2443  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2444  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2445  * 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.
2446  * 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.
2447  * 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.
2448  *
2449  * \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
2450  *             parameter is altered during the call.
2451  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2452  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2453  * \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.
2454  *
2455  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2456  */
2457 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2458                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2459 {
2460   typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2461
2462   checkFullyDefined();
2463   otherDimM1OnSameCoords.checkFullyDefined();
2464   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2466   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2468   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2469   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2470   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2471   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2472   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2473   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2474   DAInt s1=m0Part->computeFetchedNodeIds();
2475   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2476   DAInt s3=s2->buildSubstraction(s1);
2477   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2478   //
2479   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2480   int nCells2 = m0Part2->getNumberOfCells();
2481   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2482   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2483   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2484   DataArrayInt *tmp00=0,*tmp11=0;
2485   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2486   DAInt neighInit00(tmp00);
2487   DAInt neighIInit00(tmp11);
2488   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2489   DataArrayInt *idsTmp=0;
2490   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2491   DAInt ids(idsTmp);
2492   if(!b)
2493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2494   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2495   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2496   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2497   DataArrayInt *tmp0=0,*tmp1=0;
2498   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2499   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2500   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2501   DAInt neigh00(tmp0);
2502   DAInt neighI00(tmp1);
2503
2504   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2505   int seed = 0, nIter = 0;
2506   int nIterMax = nCells2+1; // Safety net for the loop
2507   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2508   hitCells->fillWithValue(-1);
2509   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2510   cellsToModifyConn0_torenum->alloc(0,1);
2511   while (nIter < nIterMax)
2512     {
2513       DAInt t = hitCells->getIdsEqual(-1);
2514       if (!t->getNumberOfTuples())
2515         break;
2516       // Connex zone without the crack (to compute the next seed really)
2517       int dnu;
2518       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2519       int cnt = 0;
2520       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2521         hitCells->setIJ(*ptr,0,1);
2522       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2523       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2524       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2525       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2526       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2527       DAInt nonHitCells = hitCells->getIdsEqual(-1);
2528       DAInt intersec = nonHitCells->buildIntersection(comple);
2529       if (intersec->getNumberOfTuples())
2530         { seed = intersec->getIJ(0,0); }
2531       else
2532         { break; }
2533       nIter++;
2534     }
2535   if (nIter >= nIterMax)
2536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2537
2538   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2539   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2540   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2541   //
2542   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2543   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2544   nodeIdsToDuplicate=s3.retn();
2545 }
2546
2547 /*!
2548  * This method operates a modification of the connectivity and coords in \b this.
2549  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2550  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2551  * 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
2552  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2553  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2554  * 
2555  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2556  * 
2557  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2558  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2559  */
2560 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2561 {
2562   int nbOfNodes=getNumberOfNodes();
2563   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2564   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2565 }
2566
2567 /*!
2568  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2569  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2570  *
2571  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2572  *
2573  * \sa renumberNodesInConn
2574  */
2575 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2576 {
2577   checkConnectivityFullyDefined();
2578   int *conn(getNodalConnectivity()->getPointer());
2579   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2580   int nbOfCells(getNumberOfCells());
2581   for(int i=0;i<nbOfCells;i++)
2582     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2583       {
2584         int& node=conn[iconn];
2585         if(node>=0)//avoid polyhedron separator
2586           {
2587             node+=offset;
2588           }
2589       }
2590   _nodal_connec->declareAsNew();
2591   updateTime();
2592 }
2593
2594 /*!
2595  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2596  *  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
2597  *  of a big mesh.
2598  */
2599 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2600 {
2601   checkConnectivityFullyDefined();
2602   int *conn(getNodalConnectivity()->getPointer());
2603   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2604   int nbOfCells(getNumberOfCells());
2605   for(int i=0;i<nbOfCells;i++)
2606     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2607       {
2608         int& node=conn[iconn];
2609         if(node>=0)//avoid polyhedron separator
2610           {
2611             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2612             if(it!=newNodeNumbersO2N.end())
2613               {
2614                 node=(*it).second;
2615               }
2616             else
2617               {
2618                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2619                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2620               }
2621           }
2622       }
2623   _nodal_connec->declareAsNew();
2624   updateTime();
2625 }
2626
2627 /*!
2628  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2629  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2630  * This method is a generalization of shiftNodeNumbersInConn().
2631  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2632  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2633  *         this->getNumberOfNodes(), in "Old to New" mode. 
2634  *         See \ref numbering for more info on renumbering modes.
2635  *  \throw If the nodal connectivity of cells is not defined.
2636  *
2637  *  \if ENABLE_EXAMPLES
2638  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2639  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2640  *  \endif
2641  */
2642 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2643 {
2644   checkConnectivityFullyDefined();
2645   int *conn=getNodalConnectivity()->getPointer();
2646   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2647   int nbOfCells(getNumberOfCells());
2648   for(int i=0;i<nbOfCells;i++)
2649     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2650       {
2651         int& node=conn[iconn];
2652         if(node>=0)//avoid polyhedron separator
2653           {
2654             node=newNodeNumbersO2N[node];
2655           }
2656       }
2657   _nodal_connec->declareAsNew();
2658   updateTime();
2659 }
2660
2661 /*!
2662  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2663  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2664  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2665  * 
2666  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2667  */
2668 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2669 {
2670   checkConnectivityFullyDefined();
2671   int *conn=getNodalConnectivity()->getPointer();
2672   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2673   int nbOfCells=getNumberOfCells();
2674   for(int i=0;i<nbOfCells;i++)
2675     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2676       {
2677         int& node=conn[iconn];
2678         if(node>=0)//avoid polyhedron separator
2679           {
2680             node+=delta;
2681           }
2682       }
2683   _nodal_connec->declareAsNew();
2684   updateTime();
2685 }
2686
2687 /*!
2688  * This method operates a modification of the connectivity in \b this.
2689  * 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.
2690  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2691  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2692  * 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
2693  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2694  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2695  * 
2696  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2697  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2698  * 
2699  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2700  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2701  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2702  */
2703 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2704 {
2705   checkConnectivityFullyDefined();
2706   std::map<int,int> m;
2707   int val=offset;
2708   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2709     m[*work]=val;
2710   int *conn=getNodalConnectivity()->getPointer();
2711   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2712   int nbOfCells=getNumberOfCells();
2713   for(int i=0;i<nbOfCells;i++)
2714     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2715       {
2716         int& node=conn[iconn];
2717         if(node>=0)//avoid polyhedron separator
2718           {
2719             std::map<int,int>::iterator it=m.find(node);
2720             if(it!=m.end())
2721               node=(*it).second;
2722           }
2723       }
2724   updateTime();
2725 }
2726
2727 /*!
2728  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2729  *
2730  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2731  * After the call of this method the number of cells remains the same as before.
2732  *
2733  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2734  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2735  * be strictly in [0;this->getNumberOfCells()).
2736  *
2737  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2738  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2739  * should be contained in[0;this->getNumberOfCells()).
2740  * 
2741  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2742  * \param check
2743  */
2744 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2745 {
2746   checkConnectivityFullyDefined();
2747   int nbCells=getNumberOfCells();
2748   const int *array=old2NewBg;
2749   if(check)
2750     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2751   //
2752   const int *conn=_nodal_connec->getConstPointer();
2753   const int *connI=_nodal_connec_index->getConstPointer();
2754   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2756   const int *n2oPtr=n2o->begin();
2757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2758   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2759   newConn->copyStringInfoFrom(*_nodal_connec);
2760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2761   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2762   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2763   //
2764   int *newC=newConn->getPointer();
2765   int *newCI=newConnI->getPointer();
2766   int loc=0;
2767   newCI[0]=loc;
2768   for(int i=0;i<nbCells;i++)
2769     {
2770       int pos=n2oPtr[i];
2771       int nbOfElts=connI[pos+1]-connI[pos];
2772       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2773       loc+=nbOfElts;
2774       newCI[i+1]=loc;
2775     }
2776   //
2777   setConnectivity(newConn,newConnI);
2778   if(check)
2779     free(const_cast<int *>(array));
2780 }
2781
2782 /*!
2783  * Finds cells whose bounding boxes intersect a given bounding box.
2784  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2785  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2786  *         zMax (if in 3D). 
2787  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2788  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2789  *         extent of the bounding box of cell to produce an addition to this bounding box.
2790  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2791  *         cells. The caller is to delete this array using decrRef() as it is no more
2792  *         needed. 
2793  *  \throw If the coordinates array is not set.
2794  *  \throw If the nodal connectivity of cells is not defined.
2795  *
2796  *  \if ENABLE_EXAMPLES
2797  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2798  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2799  *  \endif
2800  */
2801 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2802 {
2803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2804   if(getMeshDimension()==-1)
2805     {
2806       elems->pushBackSilent(0);
2807       return elems.retn();
2808     }
2809   int dim=getSpaceDimension();
2810   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2811   const int* conn      = getNodalConnectivity()->getConstPointer();
2812   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2813   const double* coords = getCoords()->getConstPointer();
2814   int nbOfCells=getNumberOfCells();
2815   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2816     {
2817       for (int i=0; i<dim; i++)
2818         {
2819           elem_bb[i*2]=std::numeric_limits<double>::max();
2820           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2821         }
2822
2823       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2824         {
2825           int node= conn[inode];
2826           if(node>=0)//avoid polyhedron separator
2827             {
2828               for (int idim=0; idim<dim; idim++)
2829                 {
2830                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2831                     {
2832                       elem_bb[idim*2] = coords[node*dim+idim] ;
2833                     }
2834                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2835                     {
2836                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2837                     }
2838                 }
2839             }
2840         }
2841       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2842         elems->pushBackSilent(ielem);
2843     }
2844   return elems.retn();
2845 }
2846
2847 /*!
2848  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2849  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2850  * added in 'elems' parameter.
2851  */
2852 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2853 {
2854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2855   if(getMeshDimension()==-1)
2856     {
2857       elems->pushBackSilent(0);
2858       return elems.retn();
2859     }
2860   int dim=getSpaceDimension();
2861   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2862   const int* conn      = getNodalConnectivity()->getConstPointer();
2863   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2864   const double* coords = getCoords()->getConstPointer();
2865   int nbOfCells=getNumberOfCells();
2866   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2867     {
2868       for (int i=0; i<dim; i++)
2869         {
2870           elem_bb[i*2]=std::numeric_limits<double>::max();
2871           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2872         }
2873
2874       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2875         {
2876           int node= conn[inode];
2877           if(node>=0)//avoid polyhedron separator
2878             {
2879               for (int idim=0; idim<dim; idim++)
2880                 {
2881                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2882                     {
2883                       elem_bb[idim*2] = coords[node*dim+idim] ;
2884                     }
2885                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2886                     {
2887                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2888                     }
2889                 }
2890             }
2891         }
2892       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2893         elems->pushBackSilent(ielem);
2894     }
2895   return elems.retn();
2896 }
2897
2898 /*!
2899  * Returns a type of a cell by its id.
2900  *  \param [in] cellId - the id of the cell of interest.
2901  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2902  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2903  */
2904 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2905 {
2906   const int *ptI=_nodal_connec_index->getConstPointer();
2907   const int *pt=_nodal_connec->getConstPointer();
2908   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2909     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2910   else
2911     {
2912       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2913       throw INTERP_KERNEL::Exception(oss.str().c_str());
2914     }
2915 }
2916
2917 /*!
2918  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2919  * This method does not throw exception if geometric type \a type is not in \a this.
2920  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2921  * The coordinates array is not considered here.
2922  *
2923  * \param [in] type the geometric type
2924  * \return cell ids in this having geometric type \a type.
2925  */
2926 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2927 {
2928
2929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2930   ret->alloc(0,1);
2931   checkConnectivityFullyDefined();
2932   int nbCells=getNumberOfCells();
2933   int mdim=getMeshDimension();
2934   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2935   if(mdim!=(int)cm.getDimension())
2936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2937   const int *ptI=_nodal_connec_index->getConstPointer();
2938   const int *pt=_nodal_connec->getConstPointer();
2939   for(int i=0;i<nbCells;i++)
2940     {
2941       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2942         ret->pushBackSilent(i);
2943     }
2944   return ret.retn();
2945 }
2946
2947 /*!
2948  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2949  */
2950 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2951 {
2952   const int *ptI=_nodal_connec_index->getConstPointer();
2953   const int *pt=_nodal_connec->getConstPointer();
2954   int nbOfCells=getNumberOfCells();
2955   int ret=0;
2956   for(int i=0;i<nbOfCells;i++)
2957     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2958       ret++;
2959   return ret;
2960 }
2961
2962 /*!
2963  * Returns the nodal connectivity of a given cell.
2964  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2965  * all returned node ids can be used in getCoordinatesOfNode().
2966  *  \param [in] cellId - an id of the cell of interest.
2967  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2968  *         cleared before the appending.
2969  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2970  */
2971 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2972 {
2973   const int *ptI=_nodal_connec_index->getConstPointer();
2974   const int *pt=_nodal_connec->getConstPointer();
2975   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2976     if(*w>=0)
2977       conn.push_back(*w);
2978 }
2979
2980 std::string MEDCouplingUMesh::simpleRepr() const
2981 {
2982   static const char msg0[]="No coordinates specified !";
2983   std::ostringstream ret;
2984   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2985   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2986   int tmpp1,tmpp2;
2987   double tt=getTime(tmpp1,tmpp2);
2988   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2989   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2990   if(_mesh_dim>=-1)
2991     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2992   else
2993     { ret << " Mesh dimension has not been set or is invalid !"; }
2994   if(_coords!=0)
2995     {
2996       const int spaceDim=getSpaceDimension();
2997       ret << spaceDim << "\nInfo attached on space dimension : ";
2998       for(int i=0;i<spaceDim;i++)
2999         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3000       ret << "\n";
3001     }
3002   else
3003     ret << msg0 << "\n";
3004   ret << "Number of nodes : ";
3005   if(_coords!=0)
3006     ret << getNumberOfNodes() << "\n";
3007   else
3008     ret << msg0 << "\n";
3009   ret << "Number of cells : ";
3010   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3011     ret << getNumberOfCells() << "\n";
3012   else
3013     ret << "No connectivity specified !" << "\n";
3014   ret << "Cell types present : ";
3015   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3016     {
3017       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3018       ret << cm.getRepr() << " ";
3019     }
3020   ret << "\n";
3021   return ret.str();
3022 }
3023
3024 std::string MEDCouplingUMesh::advancedRepr() const
3025 {
3026   std::ostringstream ret;
3027   ret << simpleRepr();
3028   ret << "\nCoordinates array : \n___________________\n\n";
3029   if(_coords)
3030     _coords->reprWithoutNameStream(ret);
3031   else
3032     ret << "No array set !\n";
3033   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3034   reprConnectivityOfThisLL(ret);
3035   return ret.str();
3036 }
3037
3038 /*!
3039  * This method returns a C++ code that is a dump of \a this.
3040  * This method will throw if this is not fully defined.
3041  */
3042 std::string MEDCouplingUMesh::cppRepr() const
3043 {
3044   static const char coordsName[]="coords";
3045   static const char connName[]="conn";
3046   static const char connIName[]="connI";
3047   checkFullyDefined();
3048   std::ostringstream ret; ret << "// coordinates" << std::endl;
3049   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3050   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3051   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3052   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3053   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3054   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3055   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3056   return ret.str();
3057 }
3058
3059 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3060 {
3061   std::ostringstream ret;
3062   reprConnectivityOfThisLL(ret);
3063   return ret.str();
3064 }
3065
3066 /*!
3067  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3068  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3069  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3070  * some algos).
3071  * 
3072  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3073  * 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
3074  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3075  */
3076 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3077 {
3078   int mdim=getMeshDimension();
3079   if(mdim<0)
3080     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3081   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3083   bool needToCpyCT=true;
3084   if(!_nodal_connec)
3085     {
3086       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3087       needToCpyCT=false;
3088     }
3089   else
3090     {
3091       tmp1=_nodal_connec;
3092       tmp1->incrRef();
3093     }
3094   if(!_nodal_connec_index)
3095     {
3096       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3097       needToCpyCT=false;
3098     }
3099   else
3100     {
3101       tmp2=_nodal_connec_index;
3102       tmp2->incrRef();
3103     }
3104   ret->setConnectivity(tmp1,tmp2,false);
3105   if(needToCpyCT)
3106     ret->_types=_types;
3107   if(!_coords)
3108     {
3109       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3110       ret->setCoords(coords);
3111     }
3112   else
3113     ret->setCoords(_coords);
3114   return ret.retn();
3115 }
3116
3117 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3118 {
3119   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3120     {
3121       int nbOfCells=getNumberOfCells();
3122       const int *c=_nodal_connec->getConstPointer();
3123       const int *ci=_nodal_connec_index->getConstPointer();
3124       for(int i=0;i<nbOfCells;i++)
3125         {
3126           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3127           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3128           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3129           stream << "\n";
3130         }
3131     }
3132   else
3133     stream << "Connectivity not defined !\n";
3134 }
3135
3136 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3137 {
3138   const int *ptI=_nodal_connec_index->getConstPointer();
3139   const int *pt=_nodal_connec->getConstPointer();
3140   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3141     return ptI[cellId+1]-ptI[cellId]-1;
3142   else
3143     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3144 }
3145
3146 /*!
3147  * Returns types of cells of the specified part of \a this mesh.
3148  * This method avoids computing sub-mesh explicitely to get its types.
3149  *  \param [in] begin - an array of cell ids of interest.
3150  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3151  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3152  *         describing the cell types. 
3153  *  \throw If the coordinates array is not set.
3154  *  \throw If the nodal connectivity of cells is not defined.
3155  *  \sa getAllGeoTypes()
3156  */
3157 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3158 {
3159   checkFullyDefined();
3160   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3161   const int *conn=_nodal_connec->getConstPointer();
3162   const int *connIndex=_nodal_connec_index->getConstPointer();
3163   for(const int *w=begin;w!=end;w++)
3164     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3165   return ret;
3166 }
3167
3168 /*!
3169  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3170  * Optionally updates
3171  * a set of types of cells constituting \a this mesh. 
3172  * This method is for advanced users having prepared their connectivity before. For
3173  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3174  *  \param [in] conn - the nodal connectivity array. 
3175  *  \param [in] connIndex - the nodal connectivity index array.
3176  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3177  *         mesh is updated.
3178  */
3179 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3180 {
3181   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3182   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3183   if(isComputingTypes)
3184     computeTypes();
3185   declareAsNew();
3186 }
3187
3188 /*!
3189  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3190  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3191  */
3192 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3193     _nodal_connec(0),_nodal_connec_index(0),
3194     _types(other._types)
3195 {
3196   if(other._nodal_connec)
3197     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3198   if(other._nodal_connec_index)
3199     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3200 }
3201
3202 MEDCouplingUMesh::~MEDCouplingUMesh()
3203 {
3204   if(_nodal_connec)
3205     _nodal_connec->decrRef();
3206   if(_nodal_connec_index)
3207     _nodal_connec_index->decrRef();
3208 }
3209
3210 /*!
3211  * Recomputes a set of cell types of \a this mesh. For more info see
3212  * \ref MEDCouplingUMeshNodalConnectivity.
3213  */
3214 void MEDCouplingUMesh::computeTypes()
3215 {
3216   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3217 }
3218
3219 /*!
3220  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3221  */
3222 void MEDCouplingUMesh::checkFullyDefined() const
3223 {
3224   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3225     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3226 }
3227
3228 /*!
3229  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3230  */
3231 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3232 {
3233   if(!_nodal_connec_index || !_nodal_connec)
3234     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3235 }
3236
3237 /*!
3238  * Returns a number of cells constituting \a this mesh. 
3239  *  \return int - the number of cells in \a this mesh.
3240  *  \throw If the nodal connectivity of cells is not defined.
3241  */
3242 int MEDCouplingUMesh::getNumberOfCells() const
3243
3244   if(_nodal_connec_index)
3245     return _nodal_connec_index->getNumberOfTuples()-1;
3246   else
3247     if(_mesh_dim==-1)
3248       return 1;
3249     else
3250       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3251 }
3252
3253 /*!
3254  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3255  * mesh. For more info see \ref meshes.
3256  *  \return int - the dimension of \a this mesh.
3257  *  \throw If the mesh dimension is not defined using setMeshDimension().
3258  */
3259 int MEDCouplingUMesh::getMeshDimension() const
3260 {
3261   if(_mesh_dim<-1)
3262     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3263   return _mesh_dim;
3264 }
3265
3266 /*!
3267  * Returns a length of the nodal connectivity array.
3268  * This method is for test reason. Normally the integer returned is not useable by
3269  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3270  *  \return int - the length of the nodal connectivity array.
3271  */
3272 int MEDCouplingUMesh::getMeshLength() const
3273 {
3274   return _nodal_connec->getNbOfElems();
3275 }
3276
3277 /*!
3278  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3279  */
3280 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3281 {
3282   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3283   tinyInfo.push_back(getMeshDimension());
3284   tinyInfo.push_back(getNumberOfCells());
3285   if(_nodal_connec)
3286     tinyInfo.push_back(getMeshLength());
3287   else
3288     tinyInfo.push_back(-1);
3289 }
3290
3291 /*!
3292  * First step of unserialization process.
3293  */
3294 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3295 {
3296   return tinyInfo[6]<=0;
3297 }
3298
3299 /*!
3300  * Second step of serialization process.
3301  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3302  * \param a1
3303  * \param a2
3304  * \param littleStrings
3305  */
3306 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3307 {
3308   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3309   if(tinyInfo[5]!=-1)
3310     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3311 }
3312
3313 /*!
3314  * Third and final step of serialization process.
3315  */
3316 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3317 {
3318   MEDCouplingPointSet::serialize(a1,a2);
3319   if(getMeshDimension()>-1)
3320     {
3321       a1=DataArrayInt::New();
3322       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3323       int *ptA1=a1->getPointer();
3324       const int *conn=getNodalConnectivity()->getConstPointer();
3325       const int *index=getNodalConnectivityIndex()->getConstPointer();
3326       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3327       std::copy(conn,conn+getMeshLength(),ptA1);
3328     }
3329   else
3330     a1=0;
3331 }
3332
3333 /*!
3334  * Second and final unserialization process.
3335  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3336  */
3337 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3338 {
3339   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3340   setMeshDimension(tinyInfo[5]);
3341   if(tinyInfo[7]!=-1)
3342     {
3343       // Connectivity
3344       const int *recvBuffer=a1->getConstPointer();
3345       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3346       myConnecIndex->alloc(tinyInfo[6]+1,1);
3347       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3348       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3349       myConnec->alloc(tinyInfo[7],1);
3350       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3351       setConnectivity(myConnec, myConnecIndex);
3352     }
3353 }
3354
3355 /*!
3356  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3357  * CellIds are given using range specified by a start an end and step.
3358  */
3359 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3360 {
3361   checkFullyDefined();
3362   int ncell=getNumberOfCells();
3363   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3364   ret->_mesh_dim=_mesh_dim;
3365   ret->setCoords(_coords);
3366   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3368   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3369   int work=start;
3370   const int *conn=_nodal_connec->getConstPointer();
3371   const int *connIndex=_nodal_connec_index->getConstPointer();
3372   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3373     {
3374       if(work>=0 && work<ncell)
3375         {
3376           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3377         }
3378       else
3379         {
3380           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3381           throw INTERP_KERNEL::Exception(oss.str().c_str());
3382         }
3383     }
3384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3385   int *newConnPtr=newConn->getPointer();
3386   std::set<INTERP_KERNEL::NormalizedCellType> types;
3387   work=start;
3388   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3389     {
3390       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3391       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3392     }
3393   ret->setConnectivity(newConn,newConnI,false);
3394   ret->_types=types;
3395   ret->copyTinyInfoFrom(this);
3396   return ret.retn();
3397 }
3398
3399 /*!
3400  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3401  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3402  * The return newly allocated mesh will share the same coordinates as \a this.
3403  */
3404 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3405 {
3406   checkConnectivityFullyDefined();
3407   int ncell=getNumberOfCells();
3408   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3409   ret->_mesh_dim=_mesh_dim;
3410   ret->setCoords(_coords);
3411   std::size_t nbOfElemsRet=std::distance(begin,end);
3412   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3413   connIndexRet[0]=0;
3414   const int *conn=_nodal_connec->getConstPointer();
3415   const int *connIndex=_nodal_connec_index->getConstPointer();
3416   int newNbring=0;
3417   for(const int *work=begin;work!=end;work++,newNbring++)
3418     {
3419       if(*work>=0 && *work<ncell)
3420         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3421       else
3422         {
3423           free(connIndexRet);
3424           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3425           throw INTERP_KERNEL::Exception(oss.str().c_str());
3426         }
3427     }
3428   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3429   int *connRetWork=connRet;
3430   std::set<INTERP_KERNEL::NormalizedCellType> types;
3431   for(const int *work=begin;work!=end;work++)
3432     {
3433       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3434       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3435     }
3436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3437   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3438   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3439   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3440   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3441   ret->_types=types;
3442   ret->copyTinyInfoFrom(this);
3443   return ret.retn();
3444 }
3445
3446 /*!
3447  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3448  * mesh.<br>
3449  * For 1D cells, the returned field contains lengths.<br>
3450  * For 2D cells, the returned field contains areas.<br>
3451  * For 3D cells, the returned field contains volumes.
3452  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3453  *         orientation, i.e. the volume is always positive.
3454  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3455  *         and one time . The caller is to delete this field using decrRef() as it is no
3456  *         more needed.
3457  */
3458 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3459 {
3460   std::string name="MeasureOfMesh_";
3461   name+=getName();
3462   int nbelem=getNumberOfCells();
3463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3464   field->setName(name);
3465   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3466   array->alloc(nbelem,1);
3467   double *area_vol=array->getPointer();
3468   field->setArray(array) ; array=0;
3469   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3470   field->synchronizeTimeWithMesh();
3471   if(getMeshDimension()!=-1)
3472     {
3473       int ipt;
3474       INTERP_KERNEL::NormalizedCellType type;
3475       int dim_space=getSpaceDimension();
3476       const double *coords=getCoords()->getConstPointer();
3477       const int *connec=getNodalConnectivity()->getConstPointer();
3478       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3479       for(int iel=0;iel<nbelem;iel++)
3480         {
3481           ipt=connec_index[iel];
3482           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3483           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);
3484         }
3485       if(isAbs)
3486         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3487     }
3488   else
3489     {
3490       area_vol[0]=std::numeric_limits<double>::max();
3491     }
3492   return field.retn();
3493 }
3494
3495 /*!
3496  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3497  * mesh.<br>
3498  * For 1D cells, the returned array contains lengths.<br>
3499  * For 2D cells, the returned array contains areas.<br>
3500  * For 3D cells, the returned array contains volumes.
3501  * This method avoids building explicitly a part of \a this mesh to perform the work.
3502  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3503  *         orientation, i.e. the volume is always positive.
3504  *  \param [in] begin - an array of cell ids of interest.
3505  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3506  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3507  *          delete this array using decrRef() as it is no more needed.
3508  * 
3509  *  \if ENABLE_EXAMPLES
3510  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3511  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3512  *  \endif
3513  *  \sa getMeasureField()
3514  */
3515 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3516 {
3517   std::string name="PartMeasureOfMesh_";
3518   name+=getName();
3519   int nbelem=(int)std::distance(begin,end);
3520   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3521   array->setName(name);
3522   array->alloc(nbelem,1);
3523   double *area_vol=array->getPointer();
3524   if(getMeshDimension()!=-1)
3525     {
3526       int ipt;
3527       INTERP_KERNEL::NormalizedCellType type;
3528       int dim_space=getSpaceDimension();
3529       const double *coords=getCoords()->getConstPointer();
3530       const int *connec=getNodalConnectivity()->getConstPointer();
3531       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3532       for(const int *iel=begin;iel!=end;iel++)
3533         {
3534           ipt=connec_index[*iel];
3535           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3536           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3537         }
3538       if(isAbs)
3539         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3540     }
3541   else
3542     {
3543       area_vol[0]=std::numeric_limits<double>::max();
3544     }
3545   return array.retn();
3546 }
3547
3548 /*!
3549  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3550  * \a this one. The returned field contains the dual cell volume for each corresponding
3551  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3552  *  the dual mesh in P1 sens of \a this.<br>
3553  * For 1D cells, the returned field contains lengths.<br>
3554  * For 2D cells, the returned field contains areas.<br>
3555  * For 3D cells, the returned field contains volumes.
3556  * This method is useful to check "P1*" conservative interpolators.
3557  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3558  *         orientation, i.e. the volume is always positive.
3559  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3560  *          nodes and one time. The caller is to delete this array using decrRef() as
3561  *          it is no more needed.
3562  */
3563 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3564 {
3565   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3566   std::string name="MeasureOnNodeOfMesh_";
3567   name+=getName();
3568   int nbNodes=getNumberOfNodes();
3569   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3570   double cst=1./((double)getMeshDimension()+1.);
3571   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3572   array->alloc(nbNodes,1);
3573   double *valsToFill=array->getPointer();
3574   std::fill(valsToFill,valsToFill+nbNodes,0.);
3575   const double *values=tmp->getArray()->getConstPointer();
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3577   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3578   getReverseNodalConnectivity(da,daInd);
3579   const int *daPtr=da->getConstPointer();
3580   const int *daIPtr=daInd->getConstPointer();
3581   for(int i=0;i<nbNodes;i++)
3582     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3583       valsToFill[i]+=cst*values[*cell];
3584   ret->setMesh(this);
3585   ret->setArray(array);
3586   return ret.retn();
3587 }
3588
3589 /*!
3590  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3591  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3592  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3593  * and are normalized.
3594  * <br> \a this can be either 
3595  * - a  2D mesh in 2D or 3D space or 
3596  * - an 1D mesh in 2D space.
3597  * 
3598  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3599  *          cells and one time. The caller is to delete this field using decrRef() as
3600  *          it is no more needed.
3601  *  \throw If the nodal connectivity of cells is not defined.
3602  *  \throw If the coordinates array is not set.
3603  *  \throw If the mesh dimension is not set.
3604  *  \throw If the mesh and space dimension is not as specified above.
3605  */
3606 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3607 {
3608   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3609     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3610   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3611   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3612   int nbOfCells=getNumberOfCells();
3613   int nbComp=getMeshDimension()+1;
3614   array->alloc(nbOfCells,nbComp);
3615   double *vals=array->getPointer();
3616   const int *connI=_nodal_connec_index->getConstPointer();
3617   const int *conn=_nodal_connec->getConstPointer();
3618   const double *coords=_coords->getConstPointer();
3619   if(getMeshDimension()==2)
3620     {
3621       if(getSpaceDimension()==3)
3622         {
3623           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3624           const double *locPtr=loc->getConstPointer();
3625           for(int i=0;i<nbOfCells;i++,vals+=3)
3626             {
3627               int offset=connI[i];
3628               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3629               double n=INTERP_KERNEL::norm<3>(vals);
3630               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3631             }
3632         }
3633       else
3634         {
3635           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3636           const double *isAbsPtr=isAbs->getArray()->begin();
3637           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3638             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3639         }
3640     }
3641   else//meshdimension==1
3642     {
3643       double tmp[2];
3644       for(int i=0;i<nbOfCells;i++)
3645         {
3646           int offset=connI[i];
3647           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3648           double n=INTERP_KERNEL::norm<2>(tmp);
3649           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3650           *vals++=-tmp[1];
3651           *vals++=tmp[0];
3652         }
3653     }
3654   ret->setArray(array);
3655   ret->setMesh(this);
3656   ret->synchronizeTimeWithSupport();
3657   return ret.retn();
3658 }
3659
3660 /*!
3661  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3662  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3663  * and are normalized.
3664  * <br> \a this can be either 
3665  * - a  2D mesh in 2D or 3D space or 
3666  * - an 1D mesh in 2D space.
3667  * 
3668  * This method avoids building explicitly a part of \a this mesh to perform the work.
3669  *  \param [in] begin - an array of cell ids of interest.
3670  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3671  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3672  *          cells and one time. The caller is to delete this field using decrRef() as
3673  *          it is no more needed.
3674  *  \throw If the nodal connectivity of cells is not defined.
3675  *  \throw If the coordinates array is not set.
3676  *  \throw If the mesh dimension is not set.
3677  *  \throw If the mesh and space dimension is not as specified above.
3678  *  \sa buildOrthogonalField()
3679  *
3680  *  \if ENABLE_EXAMPLES
3681  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3682  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3683  *  \endif
3684  */
3685 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3686 {
3687   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3688     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3689   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3690   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3691   std::size_t nbelems=std::distance(begin,end);
3692   int nbComp=getMeshDimension()+1;
3693   array->alloc((int)nbelems,nbComp);
3694   double *vals=array->getPointer();
3695   const int *connI=_nodal_connec_index->getConstPointer();
3696   const int *conn=_nodal_connec->getConstPointer();
3697   const double *coords=_coords->getConstPointer();
3698   if(getMeshDimension()==2)
3699     {
3700       if(getSpaceDimension()==3)
3701         {
3702           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3703           const double *locPtr=loc->getConstPointer();
3704           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3705             {
3706               int offset=connI[*i];
3707               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3708               double n=INTERP_KERNEL::norm<3>(vals);
3709               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3710             }
3711         }
3712       else
3713         {
3714           for(std::size_t i=0;i<nbelems;i++)
3715             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3716         }
3717     }
3718   else//meshdimension==1
3719     {
3720       double tmp[2];
3721       for(const int *i=begin;i!=end;i++)
3722         {
3723           int offset=connI[*i];
3724           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3725           double n=INTERP_KERNEL::norm<2>(tmp);
3726           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3727           *vals++=-tmp[1];
3728           *vals++=tmp[0];
3729         }
3730     }
3731   ret->setArray(array);
3732   ret->setMesh(this);
3733   ret->synchronizeTimeWithSupport();
3734   return ret.retn();
3735 }
3736
3737 /*!
3738  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3739  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3740  * and are \b not normalized.
3741  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3742  *          cells and one time. The caller is to delete this field using decrRef() as
3743  *          it is no more needed.
3744  *  \throw If the nodal connectivity of cells is not defined.
3745  *  \throw If the coordinates array is not set.
3746  *  \throw If \a this->getMeshDimension() != 1.
3747  *  \throw If \a this mesh includes cells of type other than SEG2.
3748  */
3749 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3750 {
3751   if(getMeshDimension()!=1)
3752     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3753   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3754     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3755   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3756   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3757   int nbOfCells=getNumberOfCells();
3758   int spaceDim=getSpaceDimension();
3759   array->alloc(nbOfCells,spaceDim);
3760   double *pt=array->getPointer();
3761   const double *coo=getCoords()->getConstPointer();
3762   std::vector<int> conn;
3763   conn.reserve(2);
3764   for(int i=0;i<nbOfCells;i++)
3765     {
3766       conn.resize(0);
3767       getNodeIdsOfCell(i,conn);
3768       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3769     }
3770   ret->setArray(array);
3771   ret->setMesh(this);
3772   ret->synchronizeTimeWithSupport();
3773   return ret.retn();
3774 }
3775
3776 /*!
3777  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3778  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3779  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3780  * from. If a result face is shared by two 3D cells, then the face in included twice in
3781  * the result mesh.
3782  *  \param [in] origin - 3 components of a point defining location of the plane.
3783  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3784  *         must be greater than 1e-6.
3785  *  \param [in] eps - half-thickness of the plane.
3786  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3787  *         producing correspondent 2D cells. The caller is to delete this array
3788  *         using decrRef() as it is no more needed.
3789  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3790  *         not share the node coordinates array with \a this mesh. The caller is to
3791  *         delete this mesh using decrRef() as it is no more needed.  
3792  *  \throw If the coordinates array is not set.
3793  *  \throw If the nodal connectivity of cells is not defined.
3794  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3795  *  \throw If magnitude of \a vec is less than 1e-6.
3796  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3797  *  \throw If \a this includes quadratic cells.
3798  */
3799 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3800 {
3801   checkFullyDefined();
3802   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3804   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3805   if(candidates->empty())
3806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3807   std::vector<int> nodes;
3808   DataArrayInt *cellIds1D=0;
3809   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3810   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3815   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3816   revDesc2=0; revDescIndx2=0;
3817   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3818   revDesc1=0; revDescIndx1=0;
3819   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3821   //
3822   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3823   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3824     cut3DCurve[*it]=-1;
3825   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3826   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3827   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3828                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3829                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3831   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3832   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3833   if(cellIds2->empty())
3834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3835   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3836   ret->setCoords(mDesc1->getCoords());
3837   ret->setConnectivity(conn,connI,true);
3838   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3839   return ret.retn();
3840 }
3841
3842 /*!
3843  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3844 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
3845 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3846 the result mesh.
3847  *  \param [in] origin - 3 components of a point defining location of the plane.
3848  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3849  *         must be greater than 1e-6.
3850  *  \param [in] eps - half-thickness of the plane.
3851  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3852  *         producing correspondent segments. The caller is to delete this array
3853  *         using decrRef() as it is no more needed.
3854  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3855  *         mesh in 3D space. This mesh does not share the node coordinates array with
3856  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3857  *         no more needed. 
3858  *  \throw If the coordinates array is not set.
3859  *  \throw If the nodal connectivity of cells is not defined.
3860  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3861  *  \throw If magnitude of \a vec is less than 1e-6.
3862  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3863  *  \throw If \a this includes quadratic cells.
3864  */
3865 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3866 {
3867   checkFullyDefined();
3868   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3871   if(candidates->empty())
3872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3873   std::vector<int> nodes;
3874   DataArrayInt *cellIds1D=0;
3875   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3876   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3881   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3882   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3884   //
3885   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3886   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3887     cut3DCurve[*it]=-1;
3888   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3889   int ncellsSub=subMesh->getNumberOfCells();
3890   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3891   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3892                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3893                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3895   conn->alloc(0,1);
3896   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3897   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3898   for(int i=0;i<ncellsSub;i++)
3899     {
3900       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3901         {
3902           if(cut3DSurf[i].first!=-2)
3903             {
3904               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3905               connI->pushBackSilent(conn->getNumberOfTuples());
3906               cellIds2->pushBackSilent(i);
3907             }
3908           else
3909             {
3910               int cellId3DSurf=cut3DSurf[i].second;
3911               int offset=nodalI[cellId3DSurf]+1;
3912               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3913               for(int j=0;j<nbOfEdges;j++)
3914                 {
3915                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3916                   connI->pushBackSilent(conn->getNumberOfTuples());
3917                   cellIds2->pushBackSilent(cellId3DSurf);
3918                 }
3919             }
3920         }
3921     }
3922   if(cellIds2->empty())
3923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3924   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3925   ret->setCoords(mDesc1->getCoords());
3926   ret->setConnectivity(conn,connI,true);
3927   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3928   return ret.retn();
3929 }
3930
3931 /*!
3932  * Finds cells whose bounding boxes intersect a given plane.
3933  *  \param [in] origin - 3 components of a point defining location of the plane.
3934  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3935  *         must be greater than 1e-6.
3936  *  \param [in] eps - half-thickness of the plane.
3937  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3938  *         cells. The caller is to delete this array using decrRef() as it is no more
3939  *         needed.
3940  *  \throw If the coordinates array is not set.
3941  *  \throw If the nodal connectivity of cells is not defined.
3942  *  \throw If \a this->getSpaceDimension() != 3.
3943  *  \throw If magnitude of \a vec is less than 1e-6.
3944  *  \sa buildSlice3D()
3945  */
3946 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3947 {
3948   checkFullyDefined();
3949   if(getSpaceDimension()!=3)
3950     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3951   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3952   if(normm<1e-6)
3953     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3954   double vec2[3];
3955   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3956   double angle=acos(vec[2]/normm);
3957   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3958   double bbox[6];
3959   if(angle>eps)
3960     {
3961       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3962       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3963       if(normm2/normm>1e-6)
3964         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3965       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3966       mw->setCoords(coo);
3967       mw->getBoundingBox(bbox);
3968       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3969       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3970     }
3971   else
3972     {
3973       getBoundingBox(bbox);
3974       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3975       cellIds=getCellsInBoundingBox(bbox,eps);
3976     }
3977   return cellIds.retn();
3978 }
3979
3980 /*!
3981  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3982  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3983  * No consideration of coordinate is done by this method.
3984  * 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)
3985  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3986  */
3987 bool MEDCouplingUMesh::isContiguous1D() const
3988 {
3989   if(getMeshDimension()!=1)
3990     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3991   int nbCells=getNumberOfCells();
3992   if(nbCells<1)
3993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3994   const int *connI=_nodal_connec_index->getConstPointer();
3995   const int *conn=_nodal_connec->getConstPointer();
3996   int ref=conn[connI[0]+2];
3997   for(int i=1;i<nbCells;i++)
3998     {
3999       if(conn[connI[i]+1]!=ref)
4000         return false;
4001       ref=conn[connI[i]+2];
4002     }
4003   return true;
4004 }
4005
4006 /*!
4007  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4008  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4009  * \param pt reference point of the line
4010  * \param v normalized director vector of the line
4011  * \param eps max precision before throwing an exception
4012  * \param res output of size this->getNumberOfCells
4013  */
4014 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4015 {
4016   if(getMeshDimension()!=1)
4017     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4018   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4019     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4020   if(getSpaceDimension()!=3)
4021     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4022   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4023   const double *fPtr=f->getArray()->getConstPointer();
4024   double tmp[3];
4025   for(int i=0;i<getNumberOfCells();i++)
4026     {
4027       const double *tmp1=fPtr+3*i;
4028       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4029       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4030       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4031       double n1=INTERP_KERNEL::norm<3>(tmp);
4032       n1/=INTERP_KERNEL::norm<3>(tmp1);
4033       if(n1>eps)
4034         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4035     }
4036   const double *coo=getCoords()->getConstPointer();
4037   for(int i=0;i<getNumberOfNodes();i++)
4038     {
4039       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4040       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4041       res[i]=std::accumulate(tmp,tmp+3,0.);
4042     }
4043 }
4044
4045 /*!
4046  * 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. 
4047  * \a this is expected to be a mesh so that its space dimension is equal to its
4048  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4049  * 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).
4050  *
4051  * 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
4052  * 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).
4053  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4054  *
4055  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4056  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4057  *
4058  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4059  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4060  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4061  * \return the positive value of the distance.
4062  * \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
4063  * dimension - 1.
4064  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4065  */
4066 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4067 {
4068   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4069   if(meshDim!=spaceDim-1)
4070     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4071   if(meshDim!=2 && meshDim!=1)
4072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4073   checkFullyDefined();
4074   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4075     { 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()); }
4076   DataArrayInt *ret1=0;
4077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4078   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4080   cellId=*ret1Safe->begin();
4081   return *ret0->begin();
4082 }
4083
4084 /*!
4085  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4086  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4087  * 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
4088  * 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).
4089  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4090  * 
4091  * \a this is expected to be a mesh so that its space dimension is equal to its
4092  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4093  * 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).
4094  *
4095  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4096  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4097  *
4098  * \param [in] pts the list of points in which each tuple represents a point
4099  * \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.
4100  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4101  * \throw if number of components of \a pts is not equal to the space dimension.
4102  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4103  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4104  */
4105 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4106 {
4107   if(!pts)
4108     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4109   pts->checkAllocated();
4110   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4111   if(meshDim!=spaceDim-1)
4112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4113   if(meshDim!=2 && meshDim!=1)
4114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4115   if(pts->getNumberOfComponents()!=spaceDim)
4116     {
4117       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4118       throw INTERP_KERNEL::Exception(oss.str().c_str());
4119     }
4120   checkFullyDefined();
4121   int nbCells=getNumberOfCells();
4122   if(nbCells==0)
4123     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4124   int nbOfPts=pts->getNumberOfTuples();
4125   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4127   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4128   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4129   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4130   const double *bbox(bboxArr->begin());
4131   switch(spaceDim)
4132   {
4133     case 3:
4134       {
4135         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4136         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4137           {
4138             double x=std::numeric_limits<double>::max();
4139             std::vector<int> elems;
4140             myTree.getMinDistanceOfMax(ptsPtr,x);
4141             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4142             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4143           }
4144         break;
4145       }
4146     case 2:
4147       {
4148         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4149         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4150           {
4151             double x=std::numeric_limits<double>::max();
4152             std::vector<int> elems;
4153             myTree.getMinDistanceOfMax(ptsPtr,x);
4154             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4155             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4156           }
4157         break;
4158       }
4159     default:
4160       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4161   }
4162   cellIds=ret1.retn();
4163   return ret0.retn();
4164 }
4165
4166 /// @cond INTERNAL
4167
4168 /*!
4169  * \param [in] pt the start pointer (included) of the coordinates of the point
4170  * \param [in] cellIdsBg the start pointer (included) of cellIds
4171  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4172  * \param [in] nc nodal connectivity
4173  * \param [in] ncI nodal connectivity index
4174  * \param [in,out] ret0 the min distance between \a this and the external input point
4175  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4176  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4177  */
4178 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)
4179 {
4180   cellId=-1;
4181   ret0=std::numeric_limits<double>::max();
4182   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4183     {
4184       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4185       {
4186         case INTERP_KERNEL::NORM_TRI3:
4187           {
4188             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4189             if(tmp<ret0)
4190               { ret0=tmp; cellId=*zeCell; }
4191             break;
4192           }
4193         case INTERP_KERNEL::NORM_QUAD4:
4194         case INTERP_KERNEL::NORM_POLYGON:
4195           {
4196             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4197             if(tmp<ret0)
4198               { ret0=tmp; cellId=*zeCell; }
4199             break;
4200           }
4201         default:
4202           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4203       }
4204     }
4205 }
4206
4207 /*!
4208  * \param [in] pt the start pointer (included) of the coordinates of the point
4209  * \param [in] cellIdsBg the start pointer (included) of cellIds
4210  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4211  * \param [in] nc nodal connectivity
4212  * \param [in] ncI nodal connectivity index
4213  * \param [in,out] ret0 the min distance between \a this and the external input point
4214  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4215  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4216  */
4217 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)
4218 {
4219   cellId=-1;
4220   ret0=std::numeric_limits<double>::max();
4221   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4222     {
4223       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4224       {
4225         case INTERP_KERNEL::NORM_SEG2:
4226           {
4227             std::size_t uselessEntry=0;
4228             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4229             tmp=sqrt(tmp);
4230             if(tmp<ret0)
4231               { ret0=tmp; cellId=*zeCell; }
4232             break;
4233           }
4234         default:
4235           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4236       }
4237     }
4238 }
4239 /// @endcond
4240
4241 /*!
4242  * Finds cells in contact with a ball (i.e. a point with precision). 
4243  * 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.
4244  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4245  *
4246  * \warning This method is suitable if the caller intends to evaluate only one
4247  *          point, for more points getCellsContainingPoints() is recommended as it is
4248  *          faster. 
4249  *  \param [in] pos - array of coordinates of the ball central point.
4250  *  \param [in] eps - ball radius.
4251  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4252  *         if there are no such cells.
4253  *  \throw If the coordinates array is not set.
4254  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4255  */
4256 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4257 {
4258   std::vector<int> elts;
4259   getCellsContainingPoint(pos,eps,elts);
4260   if(elts.empty())
4261     return -1;
4262   return elts.front();
4263 }
4264
4265 /*!
4266  * Finds cells in contact with a ball (i.e. a point with precision).
4267  * 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.
4268  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4269  * \warning This method is suitable if the caller intends to evaluate only one
4270  *          point, for more points getCellsContainingPoints() is recommended as it is
4271  *          faster. 
4272  *  \param [in] pos - array of coordinates of the ball central point.
4273  *  \param [in] eps - ball radius.
4274  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4275  *         before inserting ids.
4276  *  \throw If the coordinates array is not set.
4277  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4278  *
4279  *  \if ENABLE_EXAMPLES
4280  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4281  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4282  *  \endif
4283  */
4284 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4285 {
4286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4287   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4288   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4289 }
4290
4291 /// @cond INTERNAL
4292
4293 namespace ParaMEDMEM
4294 {
4295   template<const int SPACEDIMM>
4296   class DummyClsMCUG
4297   {
4298   public:
4299     static const int MY_SPACEDIM=SPACEDIMM;
4300     static const int MY_MESHDIM=8;
4301     typedef int MyConnType;
4302     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4303     // begin
4304     // useless, but for windows compilation ...
4305     const double* getCoordinatesPtr() const { return 0; }
4306     const int* getConnectivityPtr() const { return 0; }
4307     const int* getConnectivityIndexPtr() const { return 0; }
4308     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4309     // end
4310   };
4311
4312   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4313   {
4314     INTERP_KERNEL::Edge *ret(0);
4315     MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4316     m[n0]=bg[0]; m[n1]=bg[1];
4317     switch(typ)
4318     {
4319       case INTERP_KERNEL::NORM_SEG2:
4320         {
4321           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4322           break;
4323         }
4324       case INTERP_KERNEL::NORM_SEG3:
4325         {
4326           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4327           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4328           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4329           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4330           bool colinearity(inters.areColinears());
4331           delete e1; delete e2;
4332           if(colinearity)
4333             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4334           else
4335             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4336           break;
4337         }
4338       default:
4339         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4340     }
4341     return ret;
4342   }
4343
4344   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4345   {
4346     INTERP_KERNEL::Edge *ret=0;
4347     switch(typ)
4348     {
4349       case INTERP_KERNEL::NORM_SEG2:
4350         {
4351           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4352           break;
4353         }
4354       case INTERP_KERNEL::NORM_SEG3:
4355         {
4356           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4357           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4358           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4359           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4360           bool colinearity=inters.areColinears();
4361           delete e1; delete e2;
4362           if(colinearity)
4363             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4364           else
4365             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4366           mapp2[bg[2]].second=false;
4367           break;
4368         }
4369       default:
4370         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4371     }
4372     return ret;
4373   }
4374
4375   /*!
4376    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4377    * the global mesh 'mDesc'.
4378    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4379    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4380    */
4381   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4382                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4383   {
4384     mapp.clear();
4385     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.
4386     const double *coo=mDesc->getCoords()->getConstPointer();
4387     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4388     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4389     std::set<int> s;
4390     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4391       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4392     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4393       {
4394         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4395         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4396       }
4397     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4398     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4399       {
4400         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4401         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4402       }
4403     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4404       {
4405         if((*it2).second.second)
4406           mapp[(*it2).second.first]=(*it2).first;
4407         ((*it2).second.first)->decrRef();
4408       }
4409     return ret;
4410   }
4411
4412   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4413   {
4414     if(nodeId>=offset2)
4415       {
4416         int locId=nodeId-offset2;
4417         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4418       }
4419     if(nodeId>=offset1)
4420       {
4421         int locId=nodeId-offset1;
4422         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4423       }
4424     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4425   }
4426
4427   /**
4428    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4429    */
4430   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4431                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4432                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4433   {
4434     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4435       {
4436         int eltId1=abs(*desc1)-1;
4437         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4438           {
4439             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4440             if(it==mappRev.end())
4441               {
4442                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4443                 mapp[node]=*it1;
4444                 mappRev[*it1]=node;
4445               }
4446           }
4447       }
4448   }
4449 }
4450
4451 /// @endcond
4452
4453 template<int SPACEDIM>
4454 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4455                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4456 {
4457   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4458   int *eltsIndexPtr(eltsIndex->getPointer());
4459   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4460   const double *bbox(bboxArr->begin());
4461   int nbOfCells=getNumberOfCells();
4462   const int *conn=_nodal_connec->getConstPointer();
4463   const int *connI=_nodal_connec_index->getConstPointer();
4464   double bb[2*SPACEDIM];
4465   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4466   for(int i=0;i<nbOfPoints;i++)
4467     {
4468       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4469       for(int j=0;j<SPACEDIM;j++)
4470         {
4471           bb[2*j]=pos[SPACEDIM*i+j];
4472           bb[2*j+1]=pos[SPACEDIM*i+j];
4473         }
4474       std::vector<int> candidates;
4475       myTree.getIntersectingElems(bb,candidates);
4476       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4477         {
4478           int sz(connI[(*iter)+1]-connI[*iter]-1);
4479           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4480           bool status(false);
4481           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4482             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4483           else
4484             {
4485               if(SPACEDIM!=2)
4486                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4487               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4488               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4489               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4490               INTERP_KERNEL::QuadraticPolygon *pol(0);
4491               for(int j=0;j<sz;j++)
4492                 {
4493                   int nodeId(conn[connI[*iter]+1+j]);
4494                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4495                 }
4496               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4497                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4498               else
4499                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4500               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4501               double a(0.),b(0.),c(0.);
4502               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4503               status=pol->isInOrOut2(n);
4504               delete pol; n->decrRef();
4505             }
4506           if(status)
4507             {
4508               eltsIndexPtr[i+1]++;
4509               elts->pushBackSilent(*iter);
4510             }
4511         }
4512     }
4513 }
4514 /*!
4515  * Finds cells in contact with several balls (i.e. points with precision).
4516  * This method is an extension of getCellContainingPoint() and
4517  * getCellsContainingPoint() for the case of multiple points.
4518  * 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.
4519  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4520  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4521  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4522  *         this->getSpaceDimension() * \a nbOfPoints 
4523  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4524  *  \param [in] eps - radius of balls (i.e. the precision).
4525  *  \param [out] elts - vector returning ids of found cells.
4526  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4527  *         dividing cell ids in \a elts into groups each referring to one
4528  *         point. Its every element (except the last one) is an index pointing to the
4529  *         first id of a group of cells. For example cells in contact with the *i*-th
4530  *         point are described by following range of indices:
4531  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4532  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4533  *         Number of cells in contact with the *i*-th point is
4534  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4535  *  \throw If the coordinates array is not set.
4536  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4537  *
4538  *  \if ENABLE_EXAMPLES
4539  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4540  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4541  *  \endif
4542  */
4543 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4544                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4545 {
4546   int spaceDim=getSpaceDimension();
4547   int mDim=getMeshDimension();
4548   if(spaceDim==3)
4549     {
4550       if(mDim==3)
4551         {
4552           const double *coords=_coords->getConstPointer();
4553           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4554         }
4555       /*else if(mDim==2)
4556         {
4557
4558         }*/
4559       else
4560         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4561     }
4562   else if(spaceDim==2)
4563     {
4564       if(mDim==2)
4565         {
4566           const double *coords=_coords->getConstPointer();
4567           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4568         }
4569       else
4570         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4571     }
4572   else if(spaceDim==1)
4573     {
4574       if(mDim==1)
4575         {
4576           const double *coords=_coords->getConstPointer();
4577           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4578         }
4579       else
4580         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4581     }
4582   else
4583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4584 }
4585
4586 /*!
4587  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4588  * least two its edges intersect each other anywhere except their extremities. An
4589  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4590  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4591  *         cleared before filling in.
4592  *  \param [in] eps - precision.
4593  *  \throw If \a this->getMeshDimension() != 2.
4594  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4595  */
4596 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4597 {
4598   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4599   if(getMeshDimension()!=2)
4600     throw INTERP_KERNEL::Exception(msg);
4601   int spaceDim=getSpaceDimension();
4602   if(spaceDim!=2 && spaceDim!=3)
4603     throw INTERP_KERNEL::Exception(msg);
4604   const int *conn=_nodal_connec->getConstPointer();
4605   const int *connI=_nodal_connec_index->getConstPointer();
4606   int nbOfCells=getNumberOfCells();
4607   std::vector<double> cell2DinS2;
4608   for(int i=0;i<nbOfCells;i++)
4609     {
4610       int offset=connI[i];
4611       int nbOfNodesForCell=connI[i+1]-offset-1;
4612       if(nbOfNodesForCell<=3)
4613         continue;
4614       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4615       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4616       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4617         cells.push_back(i);
4618       cell2DinS2.clear();
4619     }
4620 }
4621
4622 /*!
4623  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4624  *
4625  * 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.
4626  * 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.
4627  * 
4628  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4629  * This convex envelop is computed using Jarvis march algorithm.
4630  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4631  * 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)
4632  * 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.
4633  *
4634  * \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.
4635  * \sa MEDCouplingUMesh::colinearize2D
4636  */
4637 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4638 {
4639   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4640     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4641   checkFullyDefined();
4642   const double *coords=getCoords()->getConstPointer();
4643   int nbOfCells=getNumberOfCells();
4644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4645   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4647   int *workIndexOut=nodalConnecIndexOut->getPointer();
4648   *workIndexOut=0;
4649   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4650   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4651   std::set<INTERP_KERNEL::NormalizedCellType> types;
4652   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4653   isChanged->alloc(0,1);
4654   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4655     {
4656       int pos=nodalConnecOut->getNumberOfTuples();
4657       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4658         isChanged->pushBackSilent(i);
4659       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4660       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4661     }
4662   if(isChanged->empty())
4663     return 0;
4664   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4665   _types=types;
4666   return isChanged.retn();
4667 }
4668
4669 /*!
4670  * This method is \b NOT const because it can modify \a this.
4671  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4672  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4673  * \param policy specifies the type of extrusion chosen:
4674  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4675  *   will be repeated to build each level
4676  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4677  *   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
4678  *   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
4679  *   arc.
4680  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4681  */
4682 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4683 {
4684   checkFullyDefined();
4685   mesh1D->checkFullyDefined();
4686   if(!mesh1D->isContiguous1D())
4687     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4688   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4689     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4690   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4691     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4692   if(mesh1D->getMeshDimension()!=1)
4693     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4694   bool isQuad=false;
4695   if(isPresenceOfQuadratic())
4696     {
4697       if(mesh1D->isFullyQuadratic())
4698         isQuad=true;
4699       else
4700         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4701     }
4702   int oldNbOfNodes(getNumberOfNodes());
4703   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4704   switch(policy)
4705   {
4706     case 0:
4707       {
4708         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4709         break;
4710       }
4711     case 1:
4712       {
4713         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4714         break;
4715       }
4716     default:
4717       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4718   }
4719   setCoords(newCoords);
4720   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4721   updateTime();
4722   return ret.retn();
4723 }
4724
4725 /*!
4726  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4727  * If it is not the case an exception will be thrown.
4728  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4729  * intersection of plane defined by ('origin','vec').
4730  * This method has one in/out parameter : 'cut3DCurve'.
4731  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4732  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4733  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4734  * This method will throw an exception if \a this contains a non linear segment.
4735  */
4736 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4737 {
4738   checkFullyDefined();
4739   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4740     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4741   int ncells=getNumberOfCells();
4742   int nnodes=getNumberOfNodes();
4743   double vec2[3],vec3[3],vec4[3];
4744   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4745   if(normm<1e-6)
4746     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4747   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4748   const int *conn=_nodal_connec->getConstPointer();
4749   const int *connI=_nodal_connec_index->getConstPointer();
4750   const double *coo=_coords->getConstPointer();
4751   std::vector<double> addCoo;
4752   for(int i=0;i<ncells;i++)
4753     {
4754       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4755         {
4756           if(cut3DCurve[i]==-2)
4757             {
4758               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4759               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];
4760               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4761               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4762               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4763                 {
4764                   const double *st2=coo+3*st;
4765                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4766                   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]));
4767                   if(pos>eps && pos<1-eps)
4768                     {
4769                       int nNode=((int)addCoo.size())/3;
4770                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4771                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4772                       cut3DCurve[i]=nnodes+nNode;
4773                     }
4774                 }
4775             }
4776         }
4777       else
4778         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4779     }
4780   if(!addCoo.empty())
4781     {
4782       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4783       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4784       coo2->alloc(newNbOfNodes,3);
4785       double *tmp=coo2->getPointer();
4786       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4787       std::copy(addCoo.begin(),addCoo.end(),tmp);
4788       DataArrayDouble::SetArrayIn(coo2,_coords);
4789     }
4790 }
4791
4792 /*!
4793  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4794  * \param mesh1D is the input 1D mesh used for translation computation.
4795  * \return newCoords new coords filled by this method. 
4796  */
4797 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4798 {
4799   int oldNbOfNodes=getNumberOfNodes();
4800   int nbOf1DCells=mesh1D->getNumberOfCells();
4801   int spaceDim=getSpaceDimension();
4802   DataArrayDouble *ret=DataArrayDouble::New();
4803   std::vector<bool> isQuads;
4804   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4805   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4806   double *retPtr=ret->getPointer();
4807   const double *coords=getCoords()->getConstPointer();
4808   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4809   std::vector<int> v;
4810   std::vector<double> c;
4811   double vec[3];
4812   v.reserve(3);
4813   c.reserve(6);
4814   for(int i=0;i<nbOf1DCells;i++)
4815     {
4816       v.resize(0);
4817       mesh1D->getNodeIdsOfCell(i,v);
4818       c.resize(0);
4819       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4820       mesh1D->getCoordinatesOfNode(v[0],c);
4821       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4822       for(int j=0;j<oldNbOfNodes;j++)
4823         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4824       if(isQuad)
4825         {
4826           c.resize(0);
4827           mesh1D->getCoordinatesOfNode(v[1],c);
4828           mesh1D->getCoordinatesOfNode(v[0],c);
4829           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4830           for(int j=0;j<oldNbOfNodes;j++)
4831             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4832         }
4833     }
4834   ret->copyStringInfoFrom(*getCoords());
4835   return ret;
4836 }
4837
4838 /*!
4839  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4840  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4841  * \return newCoords new coords filled by this method. 
4842  */
4843 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4844 {
4845   if(mesh1D->getSpaceDimension()==2)
4846     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4847   if(mesh1D->getSpaceDimension()==3)
4848     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4849   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4850 }
4851
4852 /*!
4853  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4854  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4855  * \return newCoords new coords filled by this method. 
4856  */
4857 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4858 {
4859   if(isQuad)
4860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4861   int oldNbOfNodes=getNumberOfNodes();
4862   int nbOf1DCells=mesh1D->getNumberOfCells();
4863   if(nbOf1DCells<2)
4864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4865   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4866   int nbOfLevsInVec=nbOf1DCells+1;
4867   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4868   double *retPtr=ret->getPointer();
4869   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4870   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4871   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4872   tmp->setCoords(tmp2);
4873   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4874   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4875   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4876   for(int i=1;i<nbOfLevsInVec;i++)
4877     {
4878       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4879       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4880       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4881       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4882       tmp->translate(vec);
4883       double tmp3[2],radius,alpha,alpha0;
4884       const double *p0=i+1<nbOfLevsInVec?begin:third;
4885       const double *p1=i+1<nbOfLevsInVec?end:begin;
4886       const double *p2=i+1<nbOfLevsInVec?third:end;
4887       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4888       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]);
4889       double angle=acos(cosangle/(radius*radius));
4890       tmp->rotate(end,0,angle);
4891       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4892     }
4893   return ret.retn();
4894 }
4895
4896 /*!
4897  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4898  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4899  * \return newCoords new coords filled by this method. 
4900  */
4901 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4902 {
4903   if(isQuad)
4904     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4905   int oldNbOfNodes=getNumberOfNodes();
4906   int nbOf1DCells=mesh1D->getNumberOfCells();
4907   if(nbOf1DCells<2)
4908     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4909   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4910   int nbOfLevsInVec=nbOf1DCells+1;
4911   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4912   double *retPtr=ret->getPointer();
4913   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4914   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4915   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4916   tmp->setCoords(tmp2);
4917   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4918   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4919   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4920   for(int i=1;i<nbOfLevsInVec;i++)
4921     {
4922       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4923       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4924       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4925       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4926       tmp->translate(vec);
4927       double tmp3[2],radius,alpha,alpha0;
4928       const double *p0=i+1<nbOfLevsInVec?begin:third;
4929       const double *p1=i+1<nbOfLevsInVec?end:begin;
4930       const double *p2=i+1<nbOfLevsInVec?third:end;
4931       double vecPlane[3]={
4932         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4933         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4934         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4935       };
4936       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4937       if(norm>1.e-7)
4938         {
4939           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4940           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4941           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4942           double s2=norm2;
4943           double c2=cos(asin(s2));
4944           double m[3][3]={
4945             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4946             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4947             {-vec2[1]*s2, vec2[0]*s2, c2}
4948           };
4949           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]};
4950           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]};
4951           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]};
4952           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4953           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]);
4954           double angle=acos(cosangle/(radius*radius));
4955           tmp->rotate(end,vecPlane,angle);
4956         }
4957       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4958     }
4959   return ret.retn();
4960 }
4961
4962 /*!
4963  * This method is private because not easy to use for end user. This method is const contrary to
4964  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4965  * the coords sorted slice by slice.
4966  * \param isQuad specifies presence of quadratic cells.
4967  */
4968 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4969 {
4970   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4971   int nbOf2DCells(getNumberOfCells());
4972   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4973   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4974   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4976   newConnI->alloc(nbOf3DCells+1,1);
4977   int *newConnIPtr(newConnI->getPointer());
4978   *newConnIPtr++=0;
4979   std::vector<int> newc;
4980   for(int j=0;j<nbOf2DCells;j++)
4981     {
4982       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4983       *newConnIPtr++=(int)newc.size();
4984     }
4985   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4986   int *newConnPtr(newConn->getPointer());
4987   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4988   newConnIPtr=newConnI->getPointer();
4989   for(int iz=0;iz<nbOf1DCells;iz++)
4990     {
4991       if(iz!=0)
4992         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4993       const int *posOfTypeOfCell(newConnIPtr);
4994       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4995         {
4996           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4997           if(icell!=*posOfTypeOfCell)
4998             {
4999               if(*iter!=-1)
5000                 *newConnPtr=(*iter)+iz*deltaPerLev;
5001               else
5002                 *newConnPtr=-1;
5003             }
5004           else
5005             {
5006               *newConnPtr=*iter;
5007               posOfTypeOfCell++;
5008             }
5009         }
5010     }
5011   ret->setConnectivity(newConn,newConnI,true);
5012   ret->setCoords(getCoords());
5013   return ret;
5014 }
5015
5016 /*!
5017  * Checks if \a this mesh is constituted by only quadratic cells.
5018  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5019  *  \throw If the coordinates array is not set.
5020  *  \throw If the nodal connectivity of cells is not defined.
5021  */
5022 bool MEDCouplingUMesh::isFullyQuadratic() const
5023 {
5024   checkFullyDefined();
5025   bool ret=true;
5026   int nbOfCells=getNumberOfCells();
5027   for(int i=0;i<nbOfCells && ret;i++)
5028     {
5029       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5030       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5031       ret=cm.isQuadratic();
5032     }
5033   return ret;
5034 }
5035
5036 /*!
5037  * Checks if \a this mesh includes any quadratic cell.
5038  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5039  *  \throw If the coordinates array is not set.
5040  *  \throw If the nodal connectivity of cells is not defined.
5041  */
5042 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5043 {
5044   checkFullyDefined();
5045   bool ret=false;
5046   int nbOfCells=getNumberOfCells();
5047   for(int i=0;i<nbOfCells && !ret;i++)
5048     {
5049       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5050       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5051       ret=cm.isQuadratic();
5052     }
5053   return ret;
5054 }
5055
5056 /*!
5057  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5058  * this mesh, it remains unchanged.
5059  *  \throw If the coordinates array is not set.
5060  *  \throw If the nodal connectivity of cells is not defined.
5061  */
5062 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5063 {
5064   checkFullyDefined();
5065   int nbOfCells=getNumberOfCells();
5066   int delta=0;
5067   const int *iciptr=_nodal_connec_index->getConstPointer();
5068   for(int i=0;i<nbOfCells;i++)
5069     {
5070       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5071       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5072       if(cm.isQuadratic())
5073         {
5074           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5075           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5076           if(!cml.isDynamic())
5077             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5078           else
5079             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5080         }
5081     }
5082   if(delta==0)
5083     return ;
5084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5086   const int *icptr=_nodal_connec->getConstPointer();
5087   newConn->alloc(getMeshLength()-delta,1);
5088   newConnI->alloc(nbOfCells+1,1);
5089   int *ocptr=newConn->getPointer();
5090   int *ociptr=newConnI->getPointer();
5091   *ociptr=0;
5092   _types.clear();
5093   for(int i=0;i<nbOfCells;i++,ociptr++)
5094     {
5095       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5096       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5097       if(!cm.isQuadratic())
5098         {
5099           _types.insert(type);
5100           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5101           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5102         }
5103       else
5104         {
5105           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5106           _types.insert(typel);
5107           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5108           int newNbOfNodes=cml.getNumberOfNodes();
5109           if(cml.isDynamic())
5110             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5111           *ocptr++=(int)typel;
5112           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5113           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5114         }
5115     }
5116   setConnectivity(newConn,newConnI,false);
5117 }
5118
5119 /*!
5120  * This method converts all linear cell in \a this to quadratic one.
5121  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5122  * 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)
5123  * 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.
5124  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5125  * end of the existing coordinates.
5126  * 
5127  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5128  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5129  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5130  * 
5131  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5132  *
5133  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5134  */
5135 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5136 {
5137   DataArrayInt *conn=0,*connI=0;
5138   DataArrayDouble *coords=0;
5139   std::set<INTERP_KERNEL::NormalizedCellType> types;
5140   checkFullyDefined();
5141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5142   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5143   int meshDim=getMeshDimension();
5144   switch(conversionType)
5145   {
5146     case 0:
5147       switch(meshDim)
5148       {
5149         case 1:
5150           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5151           connSafe=conn; connISafe=connI; coordsSafe=coords;
5152           break;
5153         case 2:
5154           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5155           connSafe=conn; connISafe=connI; coordsSafe=coords;
5156           break;
5157         case 3:
5158           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5159           connSafe=conn; connISafe=connI; coordsSafe=coords;
5160           break;
5161         default:
5162           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5163       }
5164       break;
5165         case 1:
5166           {
5167             switch(meshDim)
5168             {
5169               case 1:
5170                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5171                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5172                 break;
5173               case 2:
5174                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5175                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5176                 break;
5177               case 3:
5178                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5179                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5180                 break;
5181               default:
5182                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5183             }
5184             break;
5185           }
5186         default:
5187           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5188   }
5189   setConnectivity(connSafe,connISafe,false);
5190   _types=types;
5191   setCoords(coordsSafe);
5192   return ret.retn();
5193 }
5194
5195 /*!
5196  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5197  * so that the number of cells remains the same. Quadratic faces are converted to
5198  * polygons. This method works only for 2D meshes in
5199  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5200  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5201  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5202  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5203  *         a polylinized edge constituting the input polygon.
5204  *  \throw If the coordinates array is not set.
5205  *  \throw If the nodal connectivity of cells is not defined.
5206  *  \throw If \a this->getMeshDimension() != 2.
5207  *  \throw If \a this->getSpaceDimension() != 2.
5208  */
5209 void MEDCouplingUMesh::tessellate2D(double eps)
5210 {
5211   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5212   if(spaceDim!=2)
5213     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5214   switch(meshDim)
5215     {
5216     case 1:
5217       return tessellate2DCurveInternal(eps);
5218     case 2:
5219       return tessellate2DInternal(eps);
5220     default:
5221       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5222     }
5223 }
5224 /*!
5225  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5226  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5227  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5228  *         a sub-divided edge.
5229  *  \throw If the coordinates array is not set.
5230  *  \throw If the nodal connectivity of cells is not defined.
5231  *  \throw If \a this->getMeshDimension() != 1.
5232  *  \throw If \a this->getSpaceDimension() != 2.
5233  */
5234
5235 #if 0
5236 /*!
5237  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5238  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5239  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5240  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5241  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5242  * This method can be seen as the opposite method of colinearize2D.
5243  * 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
5244  * to avoid to modify the numbering of existing nodes.
5245  *
5246  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5247  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5248  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5249  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5250  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5251  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5252  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5253  *
5254  * \sa buildDescendingConnectivity2
5255  */
5256 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5257                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5258 {
5259   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5261   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5262   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5263     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5264   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5265     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5266   //DataArrayInt *out0(0),*outi0(0);
5267   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5268   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5269   //out0s=out0s->buildUnique(); out0s->sort(true);
5270 }
5271 #endif
5272
5273 /*!
5274  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5275  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5276  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5277  */
5278 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5279 {
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5284   int nbOfCells=getNumberOfCells();
5285   int nbOfNodes=getNumberOfNodes();
5286   const int *cPtr=_nodal_connec->getConstPointer();
5287   const int *icPtr=_nodal_connec_index->getConstPointer();
5288   int lastVal=0,offset=nbOfNodes;
5289   for(int i=0;i<nbOfCells;i++,icPtr++)
5290     {
5291       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5292       if(type==INTERP_KERNEL::NORM_SEG2)
5293         {
5294           types.insert(INTERP_KERNEL::NORM_SEG3);
5295           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5296           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5297           newConn->pushBackSilent(offset++);
5298           lastVal+=4;
5299           newConnI->pushBackSilent(lastVal);
5300           ret->pushBackSilent(i);
5301         }
5302       else
5303         {
5304           types.insert(type);
5305           lastVal+=(icPtr[1]-icPtr[0]);
5306           newConnI->pushBackSilent(lastVal);
5307           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5308         }
5309     }
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5311   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5312   return ret.retn();
5313 }
5314
5315 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
5316 {
5317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5320   //
5321   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5322   DataArrayInt *conn1D=0,*conn1DI=0;
5323   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5324   DataArrayDouble *coordsTmp=0;
5325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5326   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5328   const int *c1DPtr=conn1D->begin();
5329   const int *c1DIPtr=conn1DI->begin();
5330   int nbOfCells=getNumberOfCells();
5331   const int *cPtr=_nodal_connec->getConstPointer();
5332   const int *icPtr=_nodal_connec_index->getConstPointer();
5333   int lastVal=0;
5334   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5335     {
5336       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5337       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5338       if(!cm.isQuadratic())
5339         {
5340           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5341           types.insert(typ2); newConn->pushBackSilent(typ2);
5342           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5343           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5344             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5345           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5346           newConnI->pushBackSilent(lastVal);
5347           ret->pushBackSilent(i);
5348         }
5349       else
5350         {
5351           types.insert(typ);
5352           lastVal+=(icPtr[1]-icPtr[0]);
5353           newConnI->pushBackSilent(lastVal);
5354           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5355         }
5356     }
5357   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5358   return ret.retn();
5359 }
5360
5361 /*!
5362  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5363  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5364  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5365  */
5366 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5367 {
5368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5369   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5370   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5371 }
5372
5373 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5374 {
5375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5376   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5377   //
5378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5380   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5381   //
5382   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5383   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5384   DataArrayInt *conn1D=0,*conn1DI=0;
5385   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5386   DataArrayDouble *coordsTmp=0;
5387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5388   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5390   const int *c1DPtr=conn1D->begin();
5391   const int *c1DIPtr=conn1DI->begin();
5392   int nbOfCells=getNumberOfCells();
5393   const int *cPtr=_nodal_connec->getConstPointer();
5394   const int *icPtr=_nodal_connec_index->getConstPointer();
5395   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5396   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5397     {
5398       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5399       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5400       if(!cm.isQuadratic())
5401         {
5402           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5403           types.insert(typ2); newConn->pushBackSilent(typ2);
5404           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5405           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5406             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5407           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5408           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5409           newConnI->pushBackSilent(lastVal);
5410           ret->pushBackSilent(i);
5411         }
5412       else
5413         {
5414           types.insert(typ);
5415           lastVal+=(icPtr[1]-icPtr[0]);
5416           newConnI->pushBackSilent(lastVal);
5417           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5418         }
5419     }
5420   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5421   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5422   return ret.retn();
5423 }
5424
5425 /*!
5426  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5427  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5428  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5429  */
5430 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5431 {
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5434   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5435 }
5436
5437 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5438 {
5439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5440   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5441   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5442   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5443   //
5444   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5446   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5447   //
5448   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5449   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5450   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5451   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5452   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5455   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5457   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5459   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5460   int nbOfCells=getNumberOfCells();
5461   const int *cPtr=_nodal_connec->getConstPointer();
5462   const int *icPtr=_nodal_connec_index->getConstPointer();
5463   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5464   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5465     {
5466       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5467       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5468       if(!cm.isQuadratic())
5469         {
5470           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5471           if(typ2==INTERP_KERNEL::NORM_ERROR)
5472             {
5473               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5474               throw INTERP_KERNEL::Exception(oss.str().c_str());
5475             }
5476           types.insert(typ2); newConn->pushBackSilent(typ2);
5477           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5478           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5479             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5480           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5481             {
5482               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5483               int tmpPos=newConn->getNumberOfTuples();
5484               newConn->pushBackSilent(nodeId2);
5485               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5486             }
5487           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5488           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5489           newConnI->pushBackSilent(lastVal);
5490           ret->pushBackSilent(i);
5491         }
5492       else
5493         {
5494           types.insert(typ);
5495           lastVal+=(icPtr[1]-icPtr[0]);
5496           newConnI->pushBackSilent(lastVal);
5497           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5498         }
5499     }
5500   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5501   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5502   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5503   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5504   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5505   int *c=newConn->getPointer();
5506   const int *cI(newConnI->begin());
5507   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5508     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5509   offset=coordsTmp2Safe->getNumberOfTuples();
5510   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5511     c[cI[(*elt)+1]-1]+=offset;
5512   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5513   return ret.retn();
5514 }
5515
5516 /*!
5517  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5518  * In addition, returns an array mapping new cells to old ones. <br>
5519  * This method typically increases the number of cells in \a this mesh
5520  * but the number of nodes remains \b unchanged.
5521  * That's why the 3D splitting policies
5522  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5523  *  \param [in] policy - specifies a pattern used for splitting.
5524  * The semantic of \a policy is:
5525  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5526  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5527  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5528  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5529  *
5530  *
5531  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5532  *          an id of old cell producing it. The caller is to delete this array using
5533  *         decrRef() as it is no more needed.
5534  *
5535  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5536  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5537  *          and \a this->getMeshDimension() != 3. 
5538  *  \throw If \a policy is not one of the four discussed above.
5539  *  \throw If the nodal connectivity of cells is not defined.
5540  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5541  */
5542 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5543 {
5544   switch(policy)
5545   {
5546     case 0:
5547       return simplexizePol0();
5548     case 1:
5549       return simplexizePol1();
5550     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5551         return simplexizePlanarFace5();
5552     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5553         return simplexizePlanarFace6();
5554     default:
5555       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)");
5556   }
5557 }
5558
5559 /*!
5560  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5561  * - 1D: INTERP_KERNEL::NORM_SEG2
5562  * - 2D: INTERP_KERNEL::NORM_TRI3
5563  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5564  *
5565  * This method is useful for users that need to use P1 field services as
5566  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5567  * All these methods need mesh support containing only simplex cells.
5568  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5569  *  \throw If the coordinates array is not set.
5570  *  \throw If the nodal connectivity of cells is not defined.
5571  *  \throw If \a this->getMeshDimension() < 1.
5572  */
5573 bool MEDCouplingUMesh::areOnlySimplexCells() const
5574 {
5575   checkFullyDefined();
5576   int mdim=getMeshDimension();
5577   if(mdim<1 || mdim>3)
5578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5579   int nbCells=getNumberOfCells();
5580   const int *conn=_nodal_connec->getConstPointer();
5581   const int *connI=_nodal_connec_index->getConstPointer();
5582   for(int i=0;i<nbCells;i++)
5583     {
5584       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5585       if(!cm.isSimplex())
5586         return false;
5587     }
5588   return true;
5589 }
5590
5591 /*!
5592  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5593  */
5594 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5595 {
5596   checkConnectivityFullyDefined();
5597   if(getMeshDimension()!=2)
5598     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5599   int nbOfCells=getNumberOfCells();
5600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5601   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5602   ret->alloc(nbOfCells+nbOfCutCells,1);
5603   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5604   int *retPt=ret->getPointer();
5605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5606   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5607   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5608   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5609   int *pt=newConn->getPointer();
5610   int *ptI=newConnI->getPointer();
5611   ptI[0]=0;
5612   const int *oldc=_nodal_connec->getConstPointer();
5613   const int *ci=_nodal_connec_index->getConstPointer();
5614   for(int i=0;i<nbOfCells;i++,ci++)
5615     {
5616       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5617         {
5618           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5619             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5620           pt=std::copy(tmp,tmp+8,pt);
5621           ptI[1]=ptI[0]+4;
5622           ptI[2]=ptI[0]+8;
5623           *retPt++=i;
5624           *retPt++=i;
5625           ptI+=2;
5626         }
5627       else
5628         {
5629           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5630           ptI[1]=ptI[0]+ci[1]-ci[0];
5631           ptI++;
5632           *retPt++=i;
5633         }
5634     }
5635   _nodal_connec->decrRef();
5636   _nodal_connec=newConn.retn();
5637   _nodal_connec_index->decrRef();
5638   _nodal_connec_index=newConnI.retn();
5639   computeTypes();
5640   updateTime();
5641   return ret.retn();
5642 }
5643
5644 /*!
5645  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5646  */
5647 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5648 {
5649   checkConnectivityFullyDefined();
5650   if(getMeshDimension()!=2)
5651     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5652   int nbOfCells=getNumberOfCells();
5653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5654   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5655   ret->alloc(nbOfCells+nbOfCutCells,1);
5656   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5657   int *retPt=ret->getPointer();
5658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5660   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5661   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5662   int *pt=newConn->getPointer();
5663   int *ptI=newConnI->getPointer();
5664   ptI[0]=0;
5665   const int *oldc=_nodal_connec->getConstPointer();
5666   const int *ci=_nodal_connec_index->getConstPointer();
5667   for(int i=0;i<nbOfCells;i++,ci++)
5668     {
5669       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5670         {
5671           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5672             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5673           pt=std::copy(tmp,tmp+8,pt);
5674           ptI[1]=ptI[0]+4;
5675           ptI[2]=ptI[0]+8;
5676           *retPt++=i;
5677           *retPt++=i;
5678           ptI+=2;
5679         }
5680       else
5681         {
5682           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5683           ptI[1]=ptI[0]+ci[1]-ci[0];
5684           ptI++;
5685           *retPt++=i;
5686         }
5687     }
5688   _nodal_connec->decrRef();
5689   _nodal_connec=newConn.retn();
5690   _nodal_connec_index->decrRef();
5691   _nodal_connec_index=newConnI.retn();
5692   computeTypes();
5693   updateTime();
5694   return ret.retn();
5695 }
5696
5697 /*!
5698  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5699  */
5700 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5701 {
5702   checkConnectivityFullyDefined();
5703   if(getMeshDimension()!=3)
5704     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5705   int nbOfCells=getNumberOfCells();
5706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5707   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5708   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5709   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5710   int *retPt=ret->getPointer();
5711   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5713   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5714   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5715   int *pt=newConn->getPointer();
5716   int *ptI=newConnI->getPointer();
5717   ptI[0]=0;
5718   const int *oldc=_nodal_connec->getConstPointer();
5719   const int *ci=_nodal_connec_index->getConstPointer();
5720   for(int i=0;i<nbOfCells;i++,ci++)
5721     {
5722       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5723         {
5724           for(int j=0;j<5;j++,pt+=5,ptI++)
5725             {
5726               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5727               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];
5728               *retPt++=i;
5729               ptI[1]=ptI[0]+5;
5730             }
5731         }
5732       else
5733         {
5734           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5735           ptI[1]=ptI[0]+ci[1]-ci[0];
5736           ptI++;
5737           *retPt++=i;
5738         }
5739     }
5740   _nodal_connec->decrRef();
5741   _nodal_connec=newConn.retn();
5742   _nodal_connec_index->decrRef();
5743   _nodal_connec_index=newConnI.retn();
5744   computeTypes();
5745   updateTime();
5746   return ret.retn();
5747 }
5748
5749 /*!
5750  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5751  */
5752 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5753 {
5754   checkConnectivityFullyDefined();
5755   if(getMeshDimension()!=3)
5756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5757   int nbOfCells=getNumberOfCells();
5758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5759   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5760   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5761   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5762   int *retPt=ret->getPointer();
5763   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5764   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5765   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5766   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5767   int *pt=newConn->getPointer();
5768   int *ptI=newConnI->getPointer();
5769   ptI[0]=0;
5770   const int *oldc=_nodal_connec->getConstPointer();
5771   const int *ci=_nodal_connec_index->getConstPointer();
5772   for(int i=0;i<nbOfCells;i++,ci++)
5773     {
5774       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5775         {
5776           for(int j=0;j<6;j++,pt+=5,ptI++)
5777             {
5778               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5779               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];
5780               *retPt++=i;
5781               ptI[1]=ptI[0]+5;
5782             }
5783         }
5784       else
5785         {
5786           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5787           ptI[1]=ptI[0]+ci[1]-ci[0];
5788           ptI++;
5789           *retPt++=i;
5790         }
5791     }
5792   _nodal_connec->decrRef();
5793   _nodal_connec=newConn.retn();
5794   _nodal_connec_index->decrRef();
5795   _nodal_connec_index=newConnI.retn();
5796   computeTypes();
5797   updateTime();
5798   return ret.retn();
5799 }
5800
5801 /*!
5802  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5803  * so that the number of cells remains the same. Quadratic faces are converted to
5804  * polygons. This method works only for 2D meshes in
5805  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5806  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5807  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5808  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5809  *         a polylinized edge constituting the input polygon.
5810  *  \throw If the coordinates array is not set.
5811  *  \throw If the nodal connectivity of cells is not defined.
5812  *  \throw If \a this->getMeshDimension() != 2.
5813  *  \throw If \a this->getSpaceDimension() != 2.
5814  */
5815 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5816 {
5817   checkFullyDefined();
5818   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5819     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5820   double epsa=fabs(eps);
5821   if(epsa<std::numeric_limits<double>::min())
5822     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 !");
5823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5824   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5825   revDesc1=0; revDescIndx1=0;
5826   mDesc->tessellate2D(eps);
5827   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5828   setCoords(mDesc->getCoords());
5829 }
5830
5831 /*!
5832  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5833  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5834  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5835  *         a sub-divided edge.
5836  *  \throw If the coordinates array is not set.
5837  *  \throw If the nodal connectivity of cells is not defined.
5838  *  \throw If \a this->getMeshDimension() != 1.
5839  *  \throw If \a this->getSpaceDimension() != 2.
5840  */
5841 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5842 {
5843   checkFullyDefined();
5844   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5846   double epsa=fabs(eps);
5847   if(epsa<std::numeric_limits<double>::min())
5848     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 !");
5849   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5850   int nbCells=getNumberOfCells();
5851   int nbNodes=getNumberOfNodes();
5852   const int *conn=_nodal_connec->getConstPointer();
5853   const int *connI=_nodal_connec_index->getConstPointer();
5854   const double *coords=_coords->getConstPointer();
5855   std::vector<double> addCoo;
5856   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5858   newConnI->alloc(nbCells+1,1);
5859   int *newConnIPtr=newConnI->getPointer();
5860   *newConnIPtr=0;
5861   int tmp1[3];
5862   INTERP_KERNEL::Node *tmp2[3];
5863   std::set<INTERP_KERNEL::NormalizedCellType> types;
5864   for(int i=0;i<nbCells;i++,newConnIPtr++)
5865     {
5866       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5867       if(cm.isQuadratic())
5868         {//assert(connI[i+1]-connI[i]-1==3)
5869           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5870           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5871           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5872           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5873           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5874           if(eac)
5875             {
5876               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5877               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5878               delete eac;
5879               newConnIPtr[1]=(int)newConn.size();
5880             }
5881           else
5882             {
5883               types.insert(INTERP_KERNEL::NORM_SEG2);
5884               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5885               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5886               newConnIPtr[1]=newConnIPtr[0]+3;
5887             }
5888         }
5889       else
5890         {
5891           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5892           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5893           newConnIPtr[1]=newConnIPtr[0]+3;
5894         }
5895     }
5896   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5897     return ;
5898   _types=types;
5899   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5900   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5901   newConnArr->alloc((int)newConn.size(),1);
5902   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5903   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5904   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5905   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5906   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5907   std::copy(addCoo.begin(),addCoo.end(),work);
5908   DataArrayDouble::SetArrayIn(newCoords,_coords);
5909   updateTime();
5910 }
5911
5912 /*!
5913  * 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.
5914  * This method completly ignore coordinates.
5915  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5916  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5917  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5918  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5919  */
5920 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5921 {
5922   checkFullyDefined();
5923   if(getMeshDimension()!=2)
5924     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5925   int nbOfCells=getNumberOfCells();
5926   int *connI=_nodal_connec_index->getPointer();
5927   int newConnLgth=0;
5928   for(int i=0;i<nbOfCells;i++,connI++)
5929     {
5930       int offset=descIndex[i];
5931       int nbOfEdges=descIndex[i+1]-offset;
5932       //
5933       bool ddirect=desc[offset+nbOfEdges-1]>0;
5934       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5935       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5936       for(int j=0;j<nbOfEdges;j++)
5937         {
5938           bool direct=desc[offset+j]>0;
5939           int edgeId=std::abs(desc[offset+j])-1;
5940           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5941             {
5942               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5943               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5944               int ref2=direct?id1:id2;
5945               if(ref==ref2)
5946                 {
5947                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5948                   newConnLgth+=nbOfSubNodes-1;
5949                   ref=direct?id2:id1;
5950                 }
5951               else
5952                 {
5953                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5954                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5955                 }
5956             }
5957           else
5958             {
5959               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5960             }
5961         }
5962       newConnLgth++;//+1 is for cell type
5963       connI[1]=newConnLgth;
5964     }
5965   //
5966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5967   newConn->alloc(newConnLgth,1);
5968   int *work=newConn->getPointer();
5969   for(int i=0;i<nbOfCells;i++)
5970     {
5971       *work++=INTERP_KERNEL::NORM_POLYGON;
5972       int offset=descIndex[i];
5973       int nbOfEdges=descIndex[i+1]-offset;
5974       for(int j=0;j<nbOfEdges;j++)
5975         {
5976           bool direct=desc[offset+j]>0;
5977           int edgeId=std::abs(desc[offset+j])-1;
5978           if(direct)
5979             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5980           else
5981             {
5982               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5983               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5984               work=std::copy(it,it+nbOfSubNodes-1,work);
5985             }
5986         }
5987     }
5988   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5989   _types.clear();
5990   if(nbOfCells>0)
5991     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5992 }
5993
5994 /*!
5995  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5996  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5997  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5998  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5999  * so it can be useful to call mergeNodes() before calling this method.
6000  *  \throw If \a this->getMeshDimension() <= 1.
6001  *  \throw If the coordinates array is not set.
6002  *  \throw If the nodal connectivity of cells is not defined.
6003  */
6004 void MEDCouplingUMesh::convertDegeneratedCells()
6005 {
6006   checkFullyDefined();
6007   if(getMeshDimension()<=1)
6008     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
6009   int nbOfCells=getNumberOfCells();
6010   if(nbOfCells<1)
6011     return ;
6012   int initMeshLgth=getMeshLength();
6013   int *conn=_nodal_connec->getPointer();
6014   int *index=_nodal_connec_index->getPointer();
6015   int posOfCurCell=0;
6016   int newPos=0;
6017   int lgthOfCurCell;
6018   for(int i=0;i<nbOfCells;i++)
6019     {
6020       lgthOfCurCell=index[i+1]-posOfCurCell;
6021       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6022       int newLgth;
6023       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6024                                                                                                      conn+newPos+1,newLgth);
6025       conn[newPos]=newType;
6026       newPos+=newLgth+1;
6027       posOfCurCell=index[i+1];
6028       index[i+1]=newPos;
6029     }
6030   if(newPos!=initMeshLgth)
6031     _nodal_connec->reAlloc(newPos);
6032   computeTypes();
6033 }
6034
6035 /*!
6036  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6037  * A cell is considered to be oriented correctly if an angle between its
6038  * normal vector and a given vector is less than \c PI / \c 2.
6039  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6040  *         cells. 
6041  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6042  *         checked.
6043  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6044  *         is not cleared before filling in.
6045  *  \throw If \a this->getMeshDimension() != 2.
6046  *  \throw If \a this->getSpaceDimension() != 3.
6047  *
6048  *  \if ENABLE_EXAMPLES
6049  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6050  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6051  *  \endif
6052  */
6053 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6054 {
6055   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6056     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6057   int nbOfCells=getNumberOfCells();
6058   const int *conn=_nodal_connec->getConstPointer();
6059   const int *connI=_nodal_connec_index->getConstPointer();
6060   const double *coordsPtr=_coords->getConstPointer();
6061   for(int i=0;i<nbOfCells;i++)
6062     {
6063       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6064       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6065         {
6066           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6067           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6068             cells.push_back(i);
6069         }
6070     }
6071 }
6072
6073 /*!
6074  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6075  * considered to be oriented correctly if an angle between its normal vector and a
6076  * given vector is less than \c PI / \c 2. 
6077  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6078  *         cells. 
6079  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6080  *         checked.
6081  *  \throw If \a this->getMeshDimension() != 2.
6082  *  \throw If \a this->getSpaceDimension() != 3.
6083  *
6084  *  \if ENABLE_EXAMPLES
6085  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6086  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6087  *  \endif
6088  *
6089  *  \sa changeOrientationOfCells
6090  */
6091 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6092 {
6093   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6094     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6095   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6096   const int *connI(_nodal_connec_index->getConstPointer());
6097   const double *coordsPtr(_coords->getConstPointer());
6098   bool isModified(false);
6099   for(int i=0;i<nbOfCells;i++)
6100     {
6101       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6102       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6103         {
6104           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6105           bool isQuadratic(cm.isQuadratic());
6106           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6107             {
6108               isModified=true;
6109               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6110             }
6111         }
6112     }
6113   if(isModified)
6114     _nodal_connec->declareAsNew();
6115   updateTime();
6116 }
6117
6118 /*!
6119  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6120  *
6121  * \sa orientCorrectly2DCells
6122  */
6123 void MEDCouplingUMesh::changeOrientationOfCells()
6124 {
6125   int mdim(getMeshDimension());
6126   if(mdim!=2 && mdim!=1)
6127     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6128   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6129   const int *connI(_nodal_connec_index->getConstPointer());
6130   if(mdim==2)
6131     {//2D
6132       for(int i=0;i<nbOfCells;i++)
6133         {
6134           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6135           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6136           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6137         }
6138     }
6139   else
6140     {//1D
6141       for(int i=0;i<nbOfCells;i++)
6142         {
6143           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6144           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6145           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6146         }
6147     }
6148 }
6149
6150 /*!
6151  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6152  * oriented facets. The normal vector of the facet should point out of the cell.
6153  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6154  *         is not cleared before filling in.
6155  *  \throw If \a this->getMeshDimension() != 3.
6156  *  \throw If \a this->getSpaceDimension() != 3.
6157  *  \throw If the coordinates array is not set.
6158  *  \throw If the nodal connectivity of cells is not defined.
6159  *
6160  *  \if ENABLE_EXAMPLES
6161  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6162  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6163  *  \endif
6164  */
6165 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6166 {
6167   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6168     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6169   int nbOfCells=getNumberOfCells();
6170   const int *conn=_nodal_connec->getConstPointer();
6171   const int *connI=_nodal_connec_index->getConstPointer();
6172   const double *coordsPtr=_coords->getConstPointer();
6173   for(int i=0;i<nbOfCells;i++)
6174     {
6175       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6176       if(type==INTERP_KERNEL::NORM_POLYHED)
6177         {
6178           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6179             cells.push_back(i);
6180         }
6181     }
6182 }
6183
6184 /*!
6185  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6186  * out of the cell. 
6187  *  \throw If \a this->getMeshDimension() != 3.
6188  *  \throw If \a this->getSpaceDimension() != 3.
6189  *  \throw If the coordinates array is not set.
6190  *  \throw If the nodal connectivity of cells is not defined.
6191  *  \throw If the reparation fails.
6192  *
6193  *  \if ENABLE_EXAMPLES
6194  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6195  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6196  *  \endif
6197  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6198  */
6199 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6200 {
6201   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6202     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6203   int nbOfCells=getNumberOfCells();
6204   int *conn=_nodal_connec->getPointer();
6205   const int *connI=_nodal_connec_index->getConstPointer();
6206   const double *coordsPtr=_coords->getConstPointer();
6207   for(int i=0;i<nbOfCells;i++)
6208     {
6209       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6210       if(type==INTERP_KERNEL::NORM_POLYHED)
6211         {
6212           try
6213           {
6214               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6215                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6216           }
6217           catch(INTERP_KERNEL::Exception& e)
6218           {
6219               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6220               throw INTERP_KERNEL::Exception(oss.str().c_str());
6221           }
6222         }
6223     }
6224   updateTime();
6225 }
6226
6227 /*!
6228  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6229  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6230  * according to which the first facet of the cell should be oriented to have the normal vector
6231  * pointing out of cell.
6232  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6233  *         cells. The caller is to delete this array using decrRef() as it is no more
6234  *         needed. 
6235  *  \throw If \a this->getMeshDimension() != 3.
6236  *  \throw If \a this->getSpaceDimension() != 3.
6237  *  \throw If the coordinates array is not set.
6238  *  \throw If the nodal connectivity of cells is not defined.
6239  *
6240  *  \if ENABLE_EXAMPLES
6241  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6242  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6243  *  \endif
6244  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6245  */
6246 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6247 {
6248   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6249   if(getMeshDimension()!=3)
6250     throw INTERP_KERNEL::Exception(msg);
6251   int spaceDim=getSpaceDimension();
6252   if(spaceDim!=3)
6253     throw INTERP_KERNEL::Exception(msg);
6254   //
6255   int nbOfCells=getNumberOfCells();
6256   int *conn=_nodal_connec->getPointer();
6257   const int *connI=_nodal_connec_index->getConstPointer();
6258   const double *coo=getCoords()->getConstPointer();
6259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6260   for(int i=0;i<nbOfCells;i++)
6261     {
6262       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6263       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6264         {
6265           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6266             {
6267               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6268               cells->pushBackSilent(i);
6269             }
6270         }
6271     }
6272   return cells.retn();
6273 }
6274
6275 /*!
6276  * This method is a faster method to correct orientation of all 3D cells in \a this.
6277  * 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.
6278  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6279  * 
6280  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6281  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6282  */
6283 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6284 {
6285   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6286     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6287   int nbOfCells=getNumberOfCells();
6288   int *conn=_nodal_connec->getPointer();
6289   const int *connI=_nodal_connec_index->getConstPointer();
6290   const double *coordsPtr=_coords->getConstPointer();
6291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6292   for(int i=0;i<nbOfCells;i++)
6293     {
6294       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6295       switch(type)
6296       {
6297         case INTERP_KERNEL::NORM_TETRA4:
6298           {
6299             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6300               {
6301                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6302                 ret->pushBackSilent(i);
6303               }
6304             break;
6305           }
6306         case INTERP_KERNEL::NORM_PYRA5:
6307           {
6308             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6309               {
6310                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6311                 ret->pushBackSilent(i);
6312               }
6313             break;
6314           }
6315         case INTERP_KERNEL::NORM_PENTA6:
6316         case INTERP_KERNEL::NORM_HEXA8:
6317         case INTERP_KERNEL::NORM_HEXGP12:
6318           {
6319             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6320               {
6321                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6322                 ret->pushBackSilent(i);
6323               }
6324             break;
6325           }
6326         case INTERP_KERNEL::NORM_POLYHED:
6327           {
6328             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6329               {
6330                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6331                 ret->pushBackSilent(i);
6332               }
6333             break;
6334           }
6335         default:
6336           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 !");
6337       }
6338     }
6339   updateTime();
6340   return ret.retn();
6341 }
6342
6343 /*!
6344  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6345  * If it is not the case an exception will be thrown.
6346  * This method is fast because the first cell of \a this is used to compute the plane.
6347  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6348  * \param pos output of size at least 3 used to store a point owned of searched plane.
6349  */
6350 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6351 {
6352   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6353     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6354   const int *conn=_nodal_connec->getConstPointer();
6355   const int *connI=_nodal_connec_index->getConstPointer();
6356   const double *coordsPtr=_coords->getConstPointer();
6357   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6358   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6359 }
6360
6361 /*!
6362  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6363  * cells. Currently cells of the following types are treated:
6364  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6365  * For a cell of other type an exception is thrown.
6366  * Space dimension of a 2D mesh can be either 2 or 3.
6367  * The Edge Ratio of a cell \f$t\f$ is: 
6368  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6369  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6370  *  the smallest edge lengths of \f$t\f$.
6371  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6372  *          cells and one time, lying on \a this mesh. The caller is to delete this
6373  *          field using decrRef() as it is no more needed. 
6374  *  \throw If the coordinates array is not set.
6375  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6376  *  \throw If the connectivity data array has more than one component.
6377  *  \throw If the connectivity data array has a named component.
6378  *  \throw If the connectivity index data array has more than one component.
6379  *  \throw If the connectivity index data array has a named component.
6380  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6381  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6382  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6383  */
6384 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6385 {
6386   checkCoherency();
6387   int spaceDim=getSpaceDimension();
6388   int meshDim=getMeshDimension();
6389   if(spaceDim!=2 && spaceDim!=3)
6390     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6391   if(meshDim!=2 && meshDim!=3)
6392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6393   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6394   ret->setMesh(this);
6395   int nbOfCells=getNumberOfCells();
6396   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6397   arr->alloc(nbOfCells,1);
6398   double *pt=arr->getPointer();
6399   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6400   const int *conn=_nodal_connec->getConstPointer();
6401   const int *connI=_nodal_connec_index->getConstPointer();
6402   const double *coo=_coords->getConstPointer();
6403   double tmp[12];
6404   for(int i=0;i<nbOfCells;i++,pt++)
6405     {
6406       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6407       switch(t)
6408       {
6409         case INTERP_KERNEL::NORM_TRI3:
6410           {
6411             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6412             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6413             break;
6414           }
6415         case INTERP_KERNEL::NORM_QUAD4:
6416           {
6417             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6418             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6419             break;
6420           }
6421         case INTERP_KERNEL::NORM_TETRA4:
6422           {
6423             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6424             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6425             break;
6426           }
6427         default:
6428           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6429       }
6430       conn+=connI[i+1]-connI[i];
6431     }
6432   ret->setName("EdgeRatio");
6433   ret->synchronizeTimeWithSupport();
6434   return ret.retn();
6435 }
6436
6437 /*!
6438  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6439  * cells. Currently cells of the following types are treated:
6440  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6441  * For a cell of other type an exception is thrown.
6442  * Space dimension of a 2D mesh can be either 2 or 3.
6443  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6444  *          cells and one time, lying on \a this mesh. The caller is to delete this
6445  *          field using decrRef() as it is no more needed. 
6446  *  \throw If the coordinates array is not set.
6447  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6448  *  \throw If the connectivity data array has more than one component.
6449  *  \throw If the connectivity data array has a named component.
6450  *  \throw If the connectivity index data array has more than one component.
6451  *  \throw If the connectivity index data array has a named component.
6452  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6453  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6454  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6455  */
6456 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6457 {
6458   checkCoherency();
6459   int spaceDim=getSpaceDimension();
6460   int meshDim=getMeshDimension();
6461   if(spaceDim!=2 && spaceDim!=3)
6462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6463   if(meshDim!=2 && meshDim!=3)
6464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6465   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6466   ret->setMesh(this);
6467   int nbOfCells=getNumberOfCells();
6468   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6469   arr->alloc(nbOfCells,1);
6470   double *pt=arr->getPointer();
6471   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6472   const int *conn=_nodal_connec->getConstPointer();
6473   const int *connI=_nodal_connec_index->getConstPointer();
6474   const double *coo=_coords->getConstPointer();
6475   double tmp[12];
6476   for(int i=0;i<nbOfCells;i++,pt++)
6477     {
6478       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6479       switch(t)
6480       {
6481         case INTERP_KERNEL::NORM_TRI3:
6482           {
6483             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6484             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6485             break;
6486           }
6487         case INTERP_KERNEL::NORM_QUAD4:
6488           {
6489             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6490             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6491             break;
6492           }
6493         case INTERP_KERNEL::NORM_TETRA4:
6494           {
6495             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6496             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6497             break;
6498           }
6499         default:
6500           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6501       }
6502       conn+=connI[i+1]-connI[i];
6503     }
6504   ret->setName("AspectRatio");
6505   ret->synchronizeTimeWithSupport();
6506   return ret.retn();
6507 }
6508
6509 /*!
6510  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6511  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6512  * treated: INTERP_KERNEL::NORM_QUAD4.
6513  * For a cell of other type an exception is thrown.
6514  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6515  *          cells and one time, lying on \a this mesh. The caller is to delete this
6516  *          field using decrRef() as it is no more needed. 
6517  *  \throw If the coordinates array is not set.
6518  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6519  *  \throw If the connectivity data array has more than one component.
6520  *  \throw If the connectivity data array has a named component.
6521  *  \throw If the connectivity index data array has more than one component.
6522  *  \throw If the connectivity index data array has a named component.
6523  *  \throw If \a this->getMeshDimension() != 2.
6524  *  \throw If \a this->getSpaceDimension() != 3.
6525  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6526  */
6527 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6528 {
6529   checkCoherency();
6530   int spaceDim=getSpaceDimension();
6531   int meshDim=getMeshDimension();
6532   if(spaceDim!=3)
6533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6534   if(meshDim!=2)
6535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6536   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6537   ret->setMesh(this);
6538   int nbOfCells=getNumberOfCells();
6539   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6540   arr->alloc(nbOfCells,1);
6541   double *pt=arr->getPointer();
6542   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6543   const int *conn=_nodal_connec->getConstPointer();
6544   const int *connI=_nodal_connec_index->getConstPointer();
6545   const double *coo=_coords->getConstPointer();
6546   double tmp[12];
6547   for(int i=0;i<nbOfCells;i++,pt++)
6548     {
6549       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6550       switch(t)
6551       {
6552         case INTERP_KERNEL::NORM_QUAD4:
6553           {
6554             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6555             *pt=INTERP_KERNEL::quadWarp(tmp);
6556             break;
6557           }
6558         default:
6559           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6560       }
6561       conn+=connI[i+1]-connI[i];
6562     }
6563   ret->setName("Warp");
6564   ret->synchronizeTimeWithSupport();
6565   return ret.retn();
6566 }
6567
6568
6569 /*!
6570  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6571  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6572  * treated: INTERP_KERNEL::NORM_QUAD4.
6573  * For a cell of other type an exception is thrown.
6574  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6575  *          cells and one time, lying on \a this mesh. The caller is to delete this
6576  *          field using decrRef() as it is no more needed. 
6577  *  \throw If the coordinates array is not set.
6578  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6579  *  \throw If the connectivity data array has more than one component.
6580  *  \throw If the connectivity data array has a named component.
6581  *  \throw If the connectivity index data array has more than one component.
6582  *  \throw If the connectivity index data array has a named component.
6583  *  \throw If \a this->getMeshDimension() != 2.
6584  *  \throw If \a this->getSpaceDimension() != 3.
6585  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6586  */
6587 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6588 {
6589   checkCoherency();
6590   int spaceDim=getSpaceDimension();
6591   int meshDim=getMeshDimension();
6592   if(spaceDim!=3)
6593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6594   if(meshDim!=2)
6595     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6596   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6597   ret->setMesh(this);
6598   int nbOfCells=getNumberOfCells();
6599   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6600   arr->alloc(nbOfCells,1);
6601   double *pt=arr->getPointer();
6602   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6603   const int *conn=_nodal_connec->getConstPointer();
6604   const int *connI=_nodal_connec_index->getConstPointer();
6605   const double *coo=_coords->getConstPointer();
6606   double tmp[12];
6607   for(int i=0;i<nbOfCells;i++,pt++)
6608     {
6609       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6610       switch(t)
6611       {
6612         case INTERP_KERNEL::NORM_QUAD4:
6613           {
6614             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6615             *pt=INTERP_KERNEL::quadSkew(tmp);
6616             break;
6617           }
6618         default:
6619           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6620       }
6621       conn+=connI[i+1]-connI[i];
6622     }
6623   ret->setName("Skew");
6624   ret->synchronizeTimeWithSupport();
6625   return ret.retn();
6626 }
6627
6628 /*!
6629  * 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.
6630  *
6631  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6632  *
6633  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6634  */
6635 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6636 {
6637   checkCoherency();
6638   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6639   ret->setMesh(this);
6640   std::set<INTERP_KERNEL::NormalizedCellType> types;
6641   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6642   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6643   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6644   arr->alloc(nbCells,1);
6645   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6646     {
6647       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6648       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6649       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6650     }
6651   ret->setArray(arr);
6652   ret->setName("Diameter");
6653   return ret.retn();
6654 }
6655
6656 /*!
6657  * This method aggregate the bbox of each cell and put it into bbox parameter.
6658  * 
6659  * \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)
6660  *                         For all other cases this input parameter is ignored.
6661  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6662  * 
6663  * \throw If \a this is not fully set (coordinates and connectivity).
6664  * \throw If a cell in \a this has no valid nodeId.
6665  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6666  */
6667 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6668 {
6669   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6670   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.
6671     return getBoundingBoxForBBTreeFast();
6672   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6673     {
6674       bool presenceOfQuadratic(false);
6675       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6676         {
6677           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6678           if(cm.isQuadratic())
6679             presenceOfQuadratic=true;
6680         }
6681       if(!presenceOfQuadratic)
6682         return getBoundingBoxForBBTreeFast();
6683       if(mDim==2 && sDim==2)
6684         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6685       else
6686         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6687     }
6688   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) !");
6689 }
6690
6691 /*!
6692  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6693  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6694  * 
6695  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6696  * 
6697  * \throw If \a this is not fully set (coordinates and connectivity).
6698  * \throw If a cell in \a this has no valid nodeId.
6699  */
6700 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6701 {
6702   checkFullyDefined();
6703   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6704   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6705   double *bbox(ret->getPointer());
6706   for(int i=0;i<nbOfCells*spaceDim;i++)
6707     {
6708       bbox[2*i]=std::numeric_limits<double>::max();
6709       bbox[2*i+1]=-std::numeric_limits<double>::max();
6710     }
6711   const double *coordsPtr(_coords->getConstPointer());
6712   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6713   for(int i=0;i<nbOfCells;i++)
6714     {
6715       int offset=connI[i]+1;
6716       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6717       for(int j=0;j<nbOfNodesForCell;j++)
6718         {
6719           int nodeId=conn[offset+j];
6720           if(nodeId>=0 && nodeId<nbOfNodes)
6721             {
6722               for(int k=0;k<spaceDim;k++)
6723                 {
6724                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6725                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6726                 }
6727               kk++;
6728             }
6729         }
6730       if(kk==0)
6731         {
6732           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6733           throw INTERP_KERNEL::Exception(oss.str().c_str());
6734         }
6735     }
6736   return ret.retn();
6737 }
6738
6739 /*!
6740  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6741  * useful for 2D meshes having quadratic cells
6742  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6743  * the two extremities of the arc of circle).
6744  * 
6745  * \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)
6746  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6747  * \throw If \a this is not fully defined.
6748  * \throw If \a this is not a mesh with meshDimension equal to 2.
6749  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6750  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6751  */
6752 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6753 {
6754   checkFullyDefined();
6755   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6756   if(spaceDim!=2 || mDim!=2)
6757     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!");
6758   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6759   double *bbox(ret->getPointer());
6760   const double *coords(_coords->getConstPointer());
6761   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6762   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6763     {
6764       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6765       int sz(connI[1]-connI[0]-1);
6766       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6767       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6768       INTERP_KERNEL::QuadraticPolygon *pol(0);
6769       for(int j=0;j<sz;j++)
6770         {
6771           int nodeId(conn[*connI+1+j]);
6772           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6773         }
6774       if(!cm.isQuadratic())
6775         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6776       else
6777         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6778       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6779       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6780     }
6781   return ret.retn();
6782 }
6783
6784 /*!
6785  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6786  * useful for 2D meshes having quadratic cells
6787  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6788  * the two extremities of the arc of circle).
6789  * 
6790  * \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)
6791  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6792  * \throw If \a this is not fully defined.
6793  * \throw If \a this is not a mesh with meshDimension equal to 1.
6794  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6795  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6796  */
6797 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6798 {
6799   checkFullyDefined();
6800   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6801   if(spaceDim!=2 || mDim!=1)
6802     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!");
6803   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6804   double *bbox(ret->getPointer());
6805   const double *coords(_coords->getConstPointer());
6806   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6807   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6808     {
6809       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6810       int sz(connI[1]-connI[0]-1);
6811       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6812       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6813       INTERP_KERNEL::Edge *edge(0);
6814       for(int j=0;j<sz;j++)
6815         {
6816           int nodeId(conn[*connI+1+j]);
6817           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6818         }
6819       if(!cm.isQuadratic())
6820         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6821       else
6822         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6823       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6824       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6825     }
6826   return ret.retn();
6827 }
6828
6829 /// @cond INTERNAL
6830
6831 namespace ParaMEDMEMImpl
6832 {
6833   class ConnReader
6834   {
6835   public:
6836     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6837     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6838   private:
6839     const int *_conn;
6840     int _val;
6841   };
6842
6843   class ConnReader2
6844   {
6845   public:
6846     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6847     bool operator() (const int& pos) { return _conn[pos]==_val; }
6848   private:
6849     const int *_conn;
6850     int _val;
6851   };
6852 }
6853
6854 /// @endcond
6855
6856 /*!
6857  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6858  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6859  * \a this is composed in cell types.
6860  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6861  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6862  * This parameter is kept only for compatibility with other methode listed above.
6863  */
6864 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6865 {
6866   checkConnectivityFullyDefined();
6867   const int *conn=_nodal_connec->getConstPointer();
6868   const int *connI=_nodal_connec_index->getConstPointer();
6869   const int *work=connI;
6870   int nbOfCells=getNumberOfCells();
6871   std::size_t n=getAllGeoTypes().size();
6872   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6873   std::set<INTERP_KERNEL::NormalizedCellType> types;
6874   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6875     {
6876       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6877       if(types.find(typ)!=types.end())
6878         {
6879           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6880           oss << " is not contiguous !";
6881           throw INTERP_KERNEL::Exception(oss.str().c_str());
6882         }
6883       types.insert(typ);
6884       ret[3*i]=typ;
6885       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6886       ret[3*i+1]=(int)std::distance(work,work2);
6887       work=work2;
6888     }
6889   return ret;
6890 }
6891
6892 /*!
6893  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6894  * only for types cell, type node is not managed.
6895  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6896  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6897  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6898  * If 2 or more same geometric type is in \a code and exception is thrown too.
6899  *
6900  * This method firstly checks
6901  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6902  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6903  * an exception is thrown too.
6904  * 
6905  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6906  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6907  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6908  */
6909 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6910 {
6911   if(code.empty())
6912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6913   std::size_t sz=code.size();
6914   std::size_t n=sz/3;
6915   if(sz%3!=0)
6916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6917   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6918   int nb=0;
6919   bool isNoPflUsed=true;
6920   for(std::size_t i=0;i<n;i++)
6921     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6922       {
6923         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6924         nb+=code[3*i+1];
6925         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6926           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6927         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6928       }
6929   if(types.size()!=n)
6930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6931   if(isNoPflUsed)
6932     {
6933       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6934         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6935       if(types.size()==_types.size())
6936         return 0;
6937     }
6938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6939   ret->alloc(nb,1);
6940   int *retPtr=ret->getPointer();
6941   const int *connI=_nodal_connec_index->getConstPointer();
6942   const int *conn=_nodal_connec->getConstPointer();
6943   int nbOfCells=getNumberOfCells();
6944   const int *i=connI;
6945   int kk=0;
6946   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6947     {
6948       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6949       int offset=(int)std::distance(connI,i);
6950       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6951       int nbOfCellsOfCurType=(int)std::distance(i,j);
6952       if(code[3*kk+2]==-1)
6953         for(int k=0;k<nbOfCellsOfCurType;k++)
6954           *retPtr++=k+offset;
6955       else
6956         {
6957           int idInIdsPerType=code[3*kk+2];
6958           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6959             {
6960               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6961               if(zePfl)
6962                 {
6963                   zePfl->checkAllocated();
6964                   if(zePfl->getNumberOfComponents()==1)
6965                     {
6966                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6967                         {
6968                           if(*k>=0 && *k<nbOfCellsOfCurType)
6969                             *retPtr=(*k)+offset;
6970                           else
6971                             {
6972                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6973                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6974                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6975                             }
6976                         }
6977                     }
6978                   else
6979                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6980                 }
6981               else
6982                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6983             }
6984           else
6985             {
6986               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6987               oss << " should be in [0," << idsPerType.size() << ") !";
6988               throw INTERP_KERNEL::Exception(oss.str().c_str());
6989             }
6990         }
6991       i=j;
6992     }
6993   return ret.retn();
6994 }
6995
6996 /*!
6997  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6998  * 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.
6999  * 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.
7000  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
7001  * 
7002  * \param [in] profile
7003  * \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.
7004  * \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,
7005  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7006  * \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.
7007  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7008  * \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
7009  */
7010 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7011 {
7012   if(!profile)
7013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7014   if(profile->getNumberOfComponents()!=1)
7015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7016   checkConnectivityFullyDefined();
7017   const int *conn=_nodal_connec->getConstPointer();
7018   const int *connI=_nodal_connec_index->getConstPointer();
7019   int nbOfCells=getNumberOfCells();
7020   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7021   std::vector<int> typeRangeVals(1);
7022   for(const int *i=connI;i!=connI+nbOfCells;)
7023     {
7024       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7025       if(std::find(types.begin(),types.end(),curType)!=types.end())
7026         {
7027           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7028         }
7029       types.push_back(curType);
7030       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7031       typeRangeVals.push_back((int)std::distance(connI,i));
7032     }
7033   //
7034   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7035   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
7037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
7038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
7039   //
7040   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7041   code.resize(3*nbOfCastsFinal);
7042   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7043   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7044   for(int i=0;i<nbOfCastsFinal;i++)
7045     {
7046       int castId=castsPresent->getIJ(i,0);
7047       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7048       idsInPflPerType2.push_back(tmp3);
7049       code[3*i]=(int)types[castId];
7050       code[3*i+1]=tmp3->getNumberOfTuples();
7051       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7052       if(!tmp4->isIdentity2(typeRangeVals[castId+1]-typeRangeVals[castId]))
7053         {
7054           tmp4->copyStringInfoFrom(*profile);
7055           idsPerType2.push_back(tmp4);
7056           code[3*i+2]=(int)idsPerType2.size()-1;
7057         }
7058       else
7059         {
7060           code[3*i+2]=-1;
7061         }
7062     }
7063   std::size_t sz2=idsInPflPerType2.size();
7064   idsInPflPerType.resize(sz2);
7065   for(std::size_t i=0;i<sz2;i++)
7066     {
7067       DataArrayInt *locDa=idsInPflPerType2[i];
7068       locDa->incrRef();
7069       idsInPflPerType[i]=locDa;
7070     }
7071   std::size_t sz=idsPerType2.size();
7072   idsPerType.resize(sz);
7073   for(std::size_t i=0;i<sz;i++)
7074     {
7075       DataArrayInt *locDa=idsPerType2[i];
7076       locDa->incrRef();
7077       idsPerType[i]=locDa;
7078     }
7079 }
7080
7081 /*!
7082  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7083  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7084  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7085  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
7086  */
7087 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7088 {
7089   checkFullyDefined();
7090   nM1LevMesh->checkFullyDefined();
7091   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7093   if(_coords!=nM1LevMesh->getCoords())
7094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7095   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7096   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7097   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7099   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7100   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7101   tmp->setConnectivity(tmp0,tmp1);
7102   tmp->renumberCells(ret0->getConstPointer(),false);
7103   revDesc=tmp->getNodalConnectivity();
7104   revDescIndx=tmp->getNodalConnectivityIndex();
7105   DataArrayInt *ret=0;
7106   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7107     {
7108       int tmp2;
7109       ret->getMaxValue(tmp2);
7110       ret->decrRef();
7111       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7112       throw INTERP_KERNEL::Exception(oss.str().c_str());
7113     }
7114   nM1LevMeshIds=ret;
7115   //
7116   revDesc->incrRef();
7117   revDescIndx->incrRef();
7118   ret1->incrRef();
7119   ret0->incrRef();
7120   meshnM1Old2New=ret0;
7121   return ret1;
7122 }
7123
7124 /*!
7125  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7126  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7127  * in "Old to New" mode.
7128  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7129  *          this array using decrRef() as it is no more needed.
7130  *  \throw If the nodal connectivity of cells is not defined.
7131  */
7132 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7133 {
7134   checkConnectivityFullyDefined();
7135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7136   renumberCells(ret->getConstPointer(),false);
7137   return ret.retn();
7138 }
7139
7140 /*!
7141  * This methods checks that cells are sorted by their types.
7142  * This method makes asumption (no check) that connectivity is correctly set before calling.
7143  */
7144 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7145 {
7146   checkFullyDefined();
7147   const int *conn=_nodal_connec->getConstPointer();
7148   const int *connI=_nodal_connec_index->getConstPointer();
7149   int nbOfCells=getNumberOfCells();
7150   std::set<INTERP_KERNEL::NormalizedCellType> types;
7151   for(const int *i=connI;i!=connI+nbOfCells;)
7152     {
7153       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7154       if(types.find(curType)!=types.end())
7155         return false;
7156       types.insert(curType);
7157       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7158     }
7159   return true;
7160 }
7161
7162 /*!
7163  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7164  * The geometric type order is specified by MED file.
7165  * 
7166  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7167  */
7168 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7169 {
7170   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7171 }
7172
7173 /*!
7174  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7175  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7176  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7177  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7178  */
7179 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7180 {
7181   checkFullyDefined();
7182   const int *conn=_nodal_connec->getConstPointer();
7183   const int *connI=_nodal_connec_index->getConstPointer();
7184   int nbOfCells=getNumberOfCells();
7185   if(nbOfCells==0)
7186     return true;
7187   int lastPos=-1;
7188   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7189   for(const int *i=connI;i!=connI+nbOfCells;)
7190     {
7191       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7192       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7193       if(isTypeExists!=orderEnd)
7194         {
7195           int pos=(int)std::distance(orderBg,isTypeExists);
7196           if(pos<=lastPos)
7197             return false;
7198           lastPos=pos;
7199           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7200         }
7201       else
7202         {
7203           if(sg.find(curType)==sg.end())
7204             {
7205               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7206               sg.insert(curType);
7207             }
7208           else
7209             return false;
7210         }
7211     }
7212   return true;
7213 }
7214
7215 /*!
7216  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7217  * 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
7218  * 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'.
7219  */
7220 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7221 {
7222   checkConnectivityFullyDefined();
7223   int nbOfCells=getNumberOfCells();
7224   const int *conn=_nodal_connec->getConstPointer();
7225   const int *connI=_nodal_connec_index->getConstPointer();
7226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7228   tmpa->alloc(nbOfCells,1);
7229   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7230   tmpb->fillWithZero();
7231   int *tmp=tmpa->getPointer();
7232   int *tmp2=tmpb->getPointer();
7233   for(const int *i=connI;i!=connI+nbOfCells;i++)
7234     {
7235       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7236       if(where!=orderEnd)
7237         {
7238           int pos=(int)std::distance(orderBg,where);
7239           tmp2[pos]++;
7240           tmp[std::distance(connI,i)]=pos;
7241         }
7242       else
7243         {
7244           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7245           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7246           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7247           throw INTERP_KERNEL::Exception(oss.str().c_str());
7248         }
7249     }
7250   nbPerType=tmpb.retn();
7251   return tmpa.retn();
7252 }
7253
7254 /*!
7255  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7256  *
7257  * \return a new object containing the old to new correspondance.
7258  *
7259  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7260  */
7261 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7262 {
7263   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7264 }
7265
7266 /*!
7267  * 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.
7268  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7269  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7270  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7271  */
7272 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7273 {
7274   DataArrayInt *nbPerType=0;
7275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7276   nbPerType->decrRef();
7277   return tmpa->buildPermArrPerLevel();
7278 }
7279
7280 /*!
7281  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7282  * The number of cells remains unchanged after the call of this method.
7283  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7284  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7285  *
7286  * \return the array giving the correspondance old to new.
7287  */
7288 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7289 {
7290   checkFullyDefined();
7291   computeTypes();
7292   const int *conn=_nodal_connec->getConstPointer();
7293   const int *connI=_nodal_connec_index->getConstPointer();
7294   int nbOfCells=getNumberOfCells();
7295   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7296   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7297     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7298       {
7299         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7300         types.push_back(curType);
7301         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7302       }
7303   DataArrayInt *ret=DataArrayInt::New();
7304   ret->alloc(nbOfCells,1);
7305   int *retPtr=ret->getPointer();
7306   std::fill(retPtr,retPtr+nbOfCells,-1);
7307   int newCellId=0;
7308   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7309     {
7310       for(const int *i=connI;i!=connI+nbOfCells;i++)
7311         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7312           retPtr[std::distance(connI,i)]=newCellId++;
7313     }
7314   renumberCells(retPtr,false);
7315   return ret;
7316 }
7317
7318 /*!
7319  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7320  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7321  * This method makes asumption that connectivity is correctly set before calling.
7322  */
7323 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7324 {
7325   checkConnectivityFullyDefined();
7326   const int *conn=_nodal_connec->getConstPointer();
7327   const int *connI=_nodal_connec_index->getConstPointer();
7328   int nbOfCells=getNumberOfCells();
7329   std::vector<MEDCouplingUMesh *> ret;
7330   for(const int *i=connI;i!=connI+nbOfCells;)
7331     {
7332       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7333       int beginCellId=(int)std::distance(connI,i);
7334       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7335       int endCellId=(int)std::distance(connI,i);
7336       int sz=endCellId-beginCellId;
7337       int *cells=new int[sz];
7338       for(int j=0;j<sz;j++)
7339         cells[j]=beginCellId+j;
7340       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7341       delete [] cells;
7342       ret.push_back(m);
7343     }
7344   return ret;
7345 }
7346
7347 /*!
7348  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7349  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7350  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7351  *
7352  * \return a newly allocated instance, that the caller must manage.
7353  * \throw If \a this contains more than one geometric type.
7354  * \throw If the nodal connectivity of \a this is not fully defined.
7355  * \throw If the internal data is not coherent.
7356  */
7357 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7358 {
7359   checkConnectivityFullyDefined();
7360   if(_types.size()!=1)
7361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7362   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7363   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7364   ret->setCoords(getCoords());
7365   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7366   if(retC)
7367     {
7368       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7369       retC->setNodalConnectivity(c);
7370     }
7371   else
7372     {
7373       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7374       if(!retD)
7375         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7376       DataArrayInt *c=0,*ci=0;
7377       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7378       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7379       retD->setNodalConnectivity(cs,cis);
7380     }
7381   return ret.retn();
7382 }
7383
7384 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7385 {
7386   checkConnectivityFullyDefined();
7387   if(_types.size()!=1)
7388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7389   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7390   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7391   if(cm.isDynamic())
7392     {
7393       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7394       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7395       throw INTERP_KERNEL::Exception(oss.str().c_str());
7396     }
7397   int nbCells=getNumberOfCells();
7398   int typi=(int)typ;
7399   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7401   int *outPtr=connOut->getPointer();
7402   const int *conn=_nodal_connec->begin();
7403   const int *connI=_nodal_connec_index->begin();
7404   nbNodesPerCell++;
7405   for(int i=0;i<nbCells;i++,connI++)
7406     {
7407       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7408         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7409       else
7410         {
7411           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 << ") !";
7412           throw INTERP_KERNEL::Exception(oss.str().c_str());
7413         }
7414     }
7415   return connOut.retn();
7416 }
7417
7418 /*!
7419  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7420  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7421  * \param nodalConn
7422  * \param nodalConnI
7423  */
7424 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7425 {
7426   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7427   checkConnectivityFullyDefined();
7428   if(_types.size()!=1)
7429     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7430   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7431   if(lgth<nbCells)
7432     throw INTERP_KERNEL::Exception(msg0);
7433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7434   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7435   int *cp(c->getPointer()),*cip(ci->getPointer());
7436   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7437   cip[0]=0;
7438   for(int i=0;i<nbCells;i++,cip++,incip++)
7439     {
7440       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7441       int delta(stop-strt);
7442       if(delta>=1)
7443         {
7444           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7445             cp=std::copy(incp+strt,incp+stop,cp);
7446           else
7447             throw INTERP_KERNEL::Exception(msg0);
7448         }
7449       else
7450         throw INTERP_KERNEL::Exception(msg0);
7451       cip[1]=cip[0]+delta;
7452     }
7453   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7454 }
7455
7456 /*!
7457  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7458  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7459  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7460  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7461  * are not used here to avoid the build of big permutation array.
7462  *
7463  * \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
7464  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7465  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7466  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7467  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7468  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7469  * \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
7470  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7471  */
7472 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7473                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7474                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7475 {
7476   std::vector<const MEDCouplingUMesh *> ms2;
7477   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7478     if(*it)
7479       {
7480         (*it)->checkConnectivityFullyDefined();
7481         ms2.push_back(*it);
7482       }
7483   if(ms2.empty())
7484     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7485   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7486   int meshDim=ms2[0]->getMeshDimension();
7487   std::vector<const MEDCouplingUMesh *> m1ssm;
7488   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7489   //
7490   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7491   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7492   int fake=0,rk=0;
7493   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7494   ret1->alloc(0,1); ret2->alloc(0,1);
7495   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7496     {
7497       if(meshDim!=(*it)->getMeshDimension())
7498         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7499       if(refCoo!=(*it)->getCoords())
7500         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7501       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7502       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7503       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7504       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7505         {
7506           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7507           m1ssmSingleAuto.push_back(singleCell);
7508           m1ssmSingle.push_back(singleCell);
7509           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7510         }
7511     }
7512   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7514   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7515   for(std::size_t i=0;i<m1ssm.size();i++)
7516     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7517   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7518   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7519   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7520   return ret0.retn();
7521 }
7522
7523 /*!
7524  * This method returns a newly created DataArrayInt instance.
7525  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7526  */
7527 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7528 {
7529   checkFullyDefined();
7530   const int *conn=_nodal_connec->getConstPointer();
7531   const int *connIndex=_nodal_connec_index->getConstPointer();
7532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7533   for(const int *w=begin;w!=end;w++)
7534     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7535       ret->pushBackSilent(*w);
7536   return ret.retn();
7537 }
7538
7539 /*!
7540  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7541  * are in [0:getNumberOfCells())
7542  */
7543 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7544 {
7545   checkFullyDefined();
7546   const int *conn=_nodal_connec->getConstPointer();
7547   const int *connI=_nodal_connec_index->getConstPointer();
7548   int nbOfCells=getNumberOfCells();
7549   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7550   int *tmp=new int[nbOfCells];
7551   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7552     {
7553       int j=0;
7554       for(const int *i=connI;i!=connI+nbOfCells;i++)
7555         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7556           tmp[std::distance(connI,i)]=j++;
7557     }
7558   DataArrayInt *ret=DataArrayInt::New();
7559   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7560   ret->copyStringInfoFrom(*da);
7561   int *retPtr=ret->getPointer();
7562   const int *daPtr=da->getConstPointer();
7563   int nbOfElems=da->getNbOfElems();
7564   for(int k=0;k<nbOfElems;k++)
7565     retPtr[k]=tmp[daPtr[k]];
7566   delete [] tmp;
7567   return ret;
7568 }
7569
7570 /*!
7571  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7572  * This method \b works \b for mesh sorted by type.
7573  * cells whose ids is in 'idsPerGeoType' array.
7574  * This method conserves coords and name of mesh.
7575  */
7576 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7577 {
7578   std::vector<int> code=getDistributionOfTypes();
7579   std::size_t nOfTypesInThis=code.size()/3;
7580   int sz=0,szOfType=0;
7581   for(std::size_t i=0;i<nOfTypesInThis;i++)
7582     {
7583       if(code[3*i]!=type)
7584         sz+=code[3*i+1];
7585       else
7586         szOfType=code[3*i+1];
7587     }
7588   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7589     if(*work<0 || *work>=szOfType)
7590       {
7591         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7592         oss << ". It should be in [0," << szOfType << ") !";
7593         throw INTERP_KERNEL::Exception(oss.str().c_str());
7594       }
7595   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7596   int *idsPtr=idsTokeep->getPointer();
7597   int offset=0;
7598   for(std::size_t i=0;i<nOfTypesInThis;i++)
7599     {
7600       if(code[3*i]!=type)
7601         for(int j=0;j<code[3*i+1];j++)
7602           *idsPtr++=offset+j;
7603       else
7604         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7605       offset+=code[3*i+1];
7606     }
7607   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7608   ret->copyTinyInfoFrom(this);
7609   return ret.retn();
7610 }
7611
7612 /*!
7613  * This method returns a vector of size 'this->getNumberOfCells()'.
7614  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7615  */
7616 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7617 {
7618   int ncell=getNumberOfCells();
7619   std::vector<bool> ret(ncell);
7620   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7621   const int *c=getNodalConnectivity()->getConstPointer();
7622   for(int i=0;i<ncell;i++)
7623     {
7624       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7625       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7626       ret[i]=cm.isQuadratic();
7627     }
7628   return ret;
7629 }
7630
7631 /*!
7632  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7633  */
7634 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7635 {
7636   if(other->getType()!=UNSTRUCTURED)
7637     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7638   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7639   return MergeUMeshes(this,otherC);
7640 }
7641
7642 /*!
7643  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7644  * computed by averaging coordinates of cell nodes, so this method is not a right
7645  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7646  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7647  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7648  *          components. The caller is to delete this array using decrRef() as it is
7649  *          no more needed.
7650  *  \throw If the coordinates array is not set.
7651  *  \throw If the nodal connectivity of cells is not defined.
7652  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7653  */
7654 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7655 {
7656   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7657   int spaceDim=getSpaceDimension();
7658   int nbOfCells=getNumberOfCells();
7659   ret->alloc(nbOfCells,spaceDim);
7660   ret->copyStringInfoFrom(*getCoords());
7661   double *ptToFill=ret->getPointer();
7662   const int *nodal=_nodal_connec->getConstPointer();
7663   const int *nodalI=_nodal_connec_index->getConstPointer();
7664   const double *coor=_coords->getConstPointer();
7665   for(int i=0;i<nbOfCells;i++)
7666     {
7667       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7668       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7669       ptToFill+=spaceDim;
7670     }
7671   return ret.retn();
7672 }
7673
7674 /*!
7675  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7676  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7677  * 
7678  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7679  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7680  * 
7681  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7682  * \throw If \a this is not fully defined (coordinates and connectivity)
7683  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7684  */
7685 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7686 {
7687   checkFullyDefined();
7688   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7689   int spaceDim=getSpaceDimension();
7690   int nbOfCells=getNumberOfCells();
7691   int nbOfNodes=getNumberOfNodes();
7692   ret->alloc(nbOfCells,spaceDim);
7693   double *ptToFill=ret->getPointer();
7694   const int *nodal=_nodal_connec->getConstPointer();
7695   const int *nodalI=_nodal_connec_index->getConstPointer();
7696   const double *coor=_coords->getConstPointer();
7697   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7698     {
7699       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7700       std::fill(ptToFill,ptToFill+spaceDim,0.);
7701       if(type!=INTERP_KERNEL::NORM_POLYHED)
7702         {
7703           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7704             {
7705               if(*conn>=0 && *conn<nbOfNodes)
7706                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7707               else
7708                 {
7709                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7710                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7711                 }
7712             }
7713           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7714           if(nbOfNodesInCell>0)
7715             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7716           else
7717             {
7718               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7719               throw INTERP_KERNEL::Exception(oss.str().c_str());
7720             }
7721         }
7722       else
7723         {
7724           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7725           s.erase(-1);
7726           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7727             {
7728               if(*it>=0 && *it<nbOfNodes)
7729                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7730               else
7731                 {
7732                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7733                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7734                 }
7735             }
7736           if(!s.empty())
7737             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7738           else
7739             {
7740               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7741               throw INTERP_KERNEL::Exception(oss.str().c_str());
7742             }
7743         }
7744     }
7745   return ret.retn();
7746 }
7747
7748 /*!
7749  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7750  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7751  * are specified via an array of cell ids. 
7752  *  \warning Validity of the specified cell ids is not checked! 
7753  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7754  *  \param [in] begin - an array of cell ids of interest.
7755  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7756  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7757  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7758  *          caller is to delete this array using decrRef() as it is no more needed. 
7759  *  \throw If the coordinates array is not set.
7760  *  \throw If the nodal connectivity of cells is not defined.
7761  *
7762  *  \if ENABLE_EXAMPLES
7763  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7764  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7765  *  \endif
7766  */
7767 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7768 {
7769   DataArrayDouble *ret=DataArrayDouble::New();
7770   int spaceDim=getSpaceDimension();
7771   int nbOfTuple=(int)std::distance(begin,end);
7772   ret->alloc(nbOfTuple,spaceDim);
7773   double *ptToFill=ret->getPointer();
7774   double *tmp=new double[spaceDim];
7775   const int *nodal=_nodal_connec->getConstPointer();
7776   const int *nodalI=_nodal_connec_index->getConstPointer();
7777   const double *coor=_coords->getConstPointer();
7778   for(const int *w=begin;w!=end;w++)
7779     {
7780       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7781       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7782       ptToFill+=spaceDim;
7783     }
7784   delete [] tmp;
7785   return ret;
7786 }
7787
7788 /*!
7789  * 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".
7790  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7791  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7792  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7793  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7794  * 
7795  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7796  * \throw If spaceDim!=3 or meshDim!=2.
7797  * \throw If connectivity of \a this is invalid.
7798  * \throw If connectivity of a cell in \a this points to an invalid node.
7799  */
7800 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7801 {
7802   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7803   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7804   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7806   ret->alloc(nbOfCells,4);
7807   double *retPtr(ret->getPointer());
7808   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7809   const double *coor(_coords->begin());
7810   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7811     {
7812       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7813       if(nodalI[1]-nodalI[0]>=3)
7814         {
7815           for(int j=0;j<3;j++)
7816             {
7817               int nodeId(nodal[nodalI[0]+1+j]);
7818               if(nodeId>=0 && nodeId<nbOfNodes)
7819                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7820               else
7821                 {
7822                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7823                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7824                 }
7825             }
7826         }
7827       else
7828         {
7829           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7830           throw INTERP_KERNEL::Exception(oss.str().c_str());
7831         }
7832       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7833       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7834     }
7835   return ret.retn();
7836 }
7837
7838 /*!
7839  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7840  * 
7841  */
7842 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7843 {
7844   if(!da)
7845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7846   da->checkAllocated();
7847   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7848   ret->setCoords(da);
7849   int nbOfTuples=da->getNumberOfTuples();
7850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7852   c->alloc(2*nbOfTuples,1);
7853   cI->alloc(nbOfTuples+1,1);
7854   int *cp=c->getPointer();
7855   int *cip=cI->getPointer();
7856   *cip++=0;
7857   for(int i=0;i<nbOfTuples;i++)
7858     {
7859       *cp++=INTERP_KERNEL::NORM_POINT1;
7860       *cp++=i;
7861       *cip++=2*(i+1);
7862     }
7863   ret->setConnectivity(c,cI,true);
7864   return ret.retn();
7865 }
7866 /*!
7867  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7868  * Cells and nodes of
7869  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7870  *  \param [in] mesh1 - the first mesh.
7871  *  \param [in] mesh2 - the second mesh.
7872  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7873  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7874  *          is no more needed.
7875  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7876  *  \throw If the coordinates array is not set in none of the meshes.
7877  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7878  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7879  */
7880 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7881 {
7882   std::vector<const MEDCouplingUMesh *> tmp(2);
7883   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7884   return MergeUMeshes(tmp);
7885 }
7886
7887 /*!
7888  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7889  * Cells and nodes of
7890  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7891  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7892  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7893  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7894  *          is no more needed.
7895  *  \throw If \a a.size() == 0.
7896  *  \throw If \a a[ *i* ] == NULL.
7897  *  \throw If the coordinates array is not set in none of the meshes.
7898  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7899  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7900  */
7901 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7902 {
7903   std::size_t sz=a.size();
7904   if(sz==0)
7905     return MergeUMeshesLL(a);
7906   for(std::size_t ii=0;ii<sz;ii++)
7907     if(!a[ii])
7908       {
7909         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7910         throw INTERP_KERNEL::Exception(oss.str().c_str());
7911       }
7912   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7913   std::vector< const MEDCouplingUMesh * > aa(sz);
7914   int spaceDim=-3;
7915   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7916     {
7917       const MEDCouplingUMesh *cur=a[i];
7918       const DataArrayDouble *coo=cur->getCoords();
7919       if(coo)
7920         spaceDim=coo->getNumberOfComponents();
7921     }
7922   if(spaceDim==-3)
7923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7924   for(std::size_t i=0;i<sz;i++)
7925     {
7926       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7927       aa[i]=bb[i];
7928     }
7929   return MergeUMeshesLL(aa);
7930 }
7931
7932 /// @cond INTERNAL
7933
7934 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7935 {
7936   if(a.empty())
7937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7938   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7939   int meshDim=(*it)->getMeshDimension();
7940   int nbOfCells=(*it)->getNumberOfCells();
7941   int meshLgth=(*it++)->getMeshLength();
7942   for(;it!=a.end();it++)
7943     {
7944       if(meshDim!=(*it)->getMeshDimension())
7945         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7946       nbOfCells+=(*it)->getNumberOfCells();
7947       meshLgth+=(*it)->getMeshLength();
7948     }
7949   std::vector<const MEDCouplingPointSet *> aps(a.size());
7950   std::copy(a.begin(),a.end(),aps.begin());
7951   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7952   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7953   ret->setCoords(pts);
7954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7955   c->alloc(meshLgth,1);
7956   int *cPtr=c->getPointer();
7957   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7958   cI->alloc(nbOfCells+1,1);
7959   int *cIPtr=cI->getPointer();
7960   *cIPtr++=0;
7961   int offset=0;
7962   int offset2=0;
7963   for(it=a.begin();it!=a.end();it++)
7964     {
7965       int curNbOfCell=(*it)->getNumberOfCells();
7966       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7967       const int *curC=(*it)->_nodal_connec->getConstPointer();
7968       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7969       for(int j=0;j<curNbOfCell;j++)
7970         {
7971           const int *src=curC+curCI[j];
7972           *cPtr++=*src++;
7973           for(;src!=curC+curCI[j+1];src++,cPtr++)
7974             {
7975               if(*src!=-1)
7976                 *cPtr=*src+offset2;
7977               else
7978                 *cPtr=-1;
7979             }
7980         }
7981       offset+=curCI[curNbOfCell];
7982       offset2+=(*it)->getNumberOfNodes();
7983     }
7984   //
7985   ret->setConnectivity(c,cI,true);
7986   return ret.retn();
7987 }
7988
7989 /// @endcond
7990
7991 /*!
7992  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7993  * dimension and sharing the node coordinates array.
7994  * All cells of the first mesh precede all cells of the second mesh
7995  * within the result mesh. 
7996  *  \param [in] mesh1 - the first mesh.
7997  *  \param [in] mesh2 - the second mesh.
7998  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7999  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8000  *          is no more needed.
8001  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8002  *  \throw If the meshes do not share the node coordinates array.
8003  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8004  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8005  */
8006 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8007 {
8008   std::vector<const MEDCouplingUMesh *> tmp(2);
8009   tmp[0]=mesh1; tmp[1]=mesh2;
8010   return MergeUMeshesOnSameCoords(tmp);
8011 }
8012
8013 /*!
8014  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8015  * dimension and sharing the node coordinates array.
8016  * All cells of the *i*-th mesh precede all cells of the
8017  * (*i*+1)-th mesh within the result mesh.
8018  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8019  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8020  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8021  *          is no more needed.
8022  *  \throw If \a a.size() == 0.
8023  *  \throw If \a a[ *i* ] == NULL.
8024  *  \throw If the meshes do not share the node coordinates array.
8025  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8026  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8027  */
8028 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8029 {
8030   if(meshes.empty())
8031     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8032   for(std::size_t ii=0;ii<meshes.size();ii++)
8033     if(!meshes[ii])
8034       {
8035         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8036         throw INTERP_KERNEL::Exception(oss.str().c_str());
8037       }
8038   const DataArrayDouble *coords=meshes.front()->getCoords();
8039   int meshDim=meshes.front()->getMeshDimension();
8040   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8041   int meshLgth=0;
8042   int meshIndexLgth=0;
8043   for(;iter!=meshes.end();iter++)
8044     {
8045       if(coords!=(*iter)->getCoords())
8046         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8047       if(meshDim!=(*iter)->getMeshDimension())
8048         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8049       meshLgth+=(*iter)->getMeshLength();
8050       meshIndexLgth+=(*iter)->getNumberOfCells();
8051     }
8052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8053   nodal->alloc(meshLgth,1);
8054   int *nodalPtr=nodal->getPointer();
8055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8056   nodalIndex->alloc(meshIndexLgth+1,1);
8057   int *nodalIndexPtr=nodalIndex->getPointer();
8058   int offset=0;
8059   for(iter=meshes.begin();iter!=meshes.end();iter++)
8060     {
8061       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8062       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8063       int nbOfCells=(*iter)->getNumberOfCells();
8064       int meshLgth2=(*iter)->getMeshLength();
8065       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8066       if(iter!=meshes.begin())
8067         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8068       else
8069         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8070       offset+=meshLgth2;
8071     }
8072   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8073   ret->setName("merge");
8074   ret->setMeshDimension(meshDim);
8075   ret->setConnectivity(nodal,nodalIndex,true);
8076   ret->setCoords(coords);
8077   return ret;
8078 }
8079
8080 /*!
8081  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8082  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8083  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8084  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8085  * New" mode are returned for each input mesh.
8086  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8087  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8088  *          valid values [0,1,2], see zipConnectivityTraducer().
8089  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8090  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8091  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8092  *          no more needed.
8093  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8094  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8095  *          is no more needed.
8096  *  \throw If \a meshes.size() == 0.
8097  *  \throw If \a meshes[ *i* ] == NULL.
8098  *  \throw If the meshes do not share the node coordinates array.
8099  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8100  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8101  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8102  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8103  */
8104 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8105 {
8106   //All checks are delegated to MergeUMeshesOnSameCoords
8107   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8109   corr.resize(meshes.size());
8110   std::size_t nbOfMeshes=meshes.size();
8111   int offset=0;
8112   const int *o2nPtr=o2n->getConstPointer();
8113   for(std::size_t i=0;i<nbOfMeshes;i++)
8114     {
8115       DataArrayInt *tmp=DataArrayInt::New();
8116       int curNbOfCells=meshes[i]->getNumberOfCells();
8117       tmp->alloc(curNbOfCells,1);
8118       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8119       offset+=curNbOfCells;
8120       tmp->setName(meshes[i]->getName());
8121       corr[i]=tmp;
8122     }
8123   return ret.retn();
8124 }
8125
8126 /*!
8127  * Makes all given meshes share the nodal connectivity array. The common connectivity
8128  * array is created by concatenating the connectivity arrays of all given meshes. All
8129  * the given meshes must be of the same space dimension but dimension of cells **can
8130  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8131  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8132  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8133  *  \param [in,out] meshes - a vector of meshes to update.
8134  *  \throw If any of \a meshes is NULL.
8135  *  \throw If the coordinates array is not set in any of \a meshes.
8136  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8137  *  \throw If \a meshes are of different space dimension.
8138  */
8139 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8140 {
8141   std::size_t sz=meshes.size();
8142   if(sz==0 || sz==1)
8143     return;
8144   std::vector< const DataArrayDouble * > coords(meshes.size());
8145   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8146   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8147     {
8148       if((*it))
8149         {
8150           (*it)->checkConnectivityFullyDefined();
8151           const DataArrayDouble *coo=(*it)->getCoords();
8152           if(coo)
8153             *it2=coo;
8154           else
8155             {
8156               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8157               oss << " has no coordinate array defined !";
8158               throw INTERP_KERNEL::Exception(oss.str().c_str());
8159             }
8160         }
8161       else
8162         {
8163           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8164           oss << " is null !";
8165           throw INTERP_KERNEL::Exception(oss.str().c_str());
8166         }
8167     }
8168   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8169   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8170   int offset=(*it)->getNumberOfNodes();
8171   (*it++)->setCoords(res);
8172   for(;it!=meshes.end();it++)
8173     {
8174       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8175       (*it)->setCoords(res);
8176       (*it)->shiftNodeNumbersInConn(offset);
8177       offset+=oldNumberOfNodes;
8178     }
8179 }
8180
8181 /*!
8182  * Merges nodes coincident with a given precision within all given meshes that share
8183  * the nodal connectivity array. The given meshes **can be of different** mesh
8184  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8185  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8186  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8187  *  \param [in,out] meshes - a vector of meshes to update.
8188  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8189  *  \throw If any of \a meshes is NULL.
8190  *  \throw If the \a meshes do not share the same node coordinates array.
8191  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8192  */
8193 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8194 {
8195   if(meshes.empty())
8196     return ;
8197   std::set<const DataArrayDouble *> s;
8198   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8199     {
8200       if(*it)
8201         s.insert((*it)->getCoords());
8202       else
8203         {
8204           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 !";
8205           throw INTERP_KERNEL::Exception(oss.str().c_str());
8206         }
8207     }
8208   if(s.size()!=1)
8209     {
8210       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 !";
8211       throw INTERP_KERNEL::Exception(oss.str().c_str());
8212     }
8213   const DataArrayDouble *coo=*(s.begin());
8214   if(!coo)
8215     return;
8216   //
8217   DataArrayInt *comm,*commI;
8218   coo->findCommonTuples(eps,-1,comm,commI);
8219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8220   int oldNbOfNodes=coo->getNumberOfTuples();
8221   int newNbOfNodes;
8222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8223   if(oldNbOfNodes==newNbOfNodes)
8224     return ;
8225   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8226   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8227     {
8228       (*it)->renumberNodesInConn(o2n->getConstPointer());
8229       (*it)->setCoords(newCoords);
8230     } 
8231 }
8232
8233 /*!
8234  * 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.
8235  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8236  * \param isQuad specifies the policy of connectivity.
8237  * @ret in/out parameter in which the result will be append
8238  */
8239 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8240 {
8241   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8242   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8243   ret.push_back(cm.getExtrudedType());
8244   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8245   switch(flatType)
8246   {
8247     case INTERP_KERNEL::NORM_POINT1:
8248       {
8249         ret.push_back(connBg[1]);
8250         ret.push_back(connBg[1]+nbOfNodesPerLev);
8251         break;
8252       }
8253     case INTERP_KERNEL::NORM_SEG2:
8254       {
8255         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8256         ret.insert(ret.end(),conn,conn+4);
8257         break;
8258       }
8259     case INTERP_KERNEL::NORM_SEG3:
8260       {
8261         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8262         ret.insert(ret.end(),conn,conn+8);
8263         break;
8264       }
8265     case INTERP_KERNEL::NORM_QUAD4:
8266       {
8267         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8268         ret.insert(ret.end(),conn,conn+8);
8269         break;
8270       }
8271     case INTERP_KERNEL::NORM_TRI3:
8272       {
8273         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8274         ret.insert(ret.end(),conn,conn+6);
8275         break;
8276       }
8277     case INTERP_KERNEL::NORM_TRI6:
8278       {
8279         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,
8280           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8281         ret.insert(ret.end(),conn,conn+15);
8282         break;
8283       }
8284     case INTERP_KERNEL::NORM_QUAD8:
8285       {
8286         int conn[20]={
8287           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8288           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8289           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8290         };
8291         ret.insert(ret.end(),conn,conn+20);
8292         break;
8293       }
8294     case INTERP_KERNEL::NORM_POLYGON:
8295       {
8296         std::back_insert_iterator< std::vector<int> > ii(ret);
8297         std::copy(connBg+1,connEnd,ii);
8298         *ii++=-1;
8299         std::reverse_iterator<const int *> rConnBg(connEnd);
8300         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8301         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8302         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8303         for(std::size_t i=0;i<nbOfRadFaces;i++)
8304           {
8305             *ii++=-1;
8306             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8307             std::copy(conn,conn+4,ii);
8308           }
8309         break;
8310       }
8311     default:
8312       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8313   }
8314 }
8315
8316 /*!
8317  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8318  */
8319 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8320 {
8321   std::size_t i, ip1;
8322   double v[3]={0.,0.,0.};
8323   std::size_t sz=std::distance(begin,end);
8324   if(isQuadratic)
8325     sz/=2;
8326   for(i=0;i<sz;i++)
8327     {
8328       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];
8329       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8330       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8331     }
8332   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8333
8334   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8335   // SEG3 forming a circle):
8336   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8337     {
8338       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8339       for(std::size_t j=0;j<sz;j++)
8340         {
8341           if (j%2)  // current point i is quadratic, next point i+1 is standard
8342             {
8343               i = sz+j;
8344               ip1 = (j+1)%sz; // ip1 = "i+1"
8345             }
8346           else      // current point i is standard, next point i+1 is quadratic
8347             {
8348               i = j;
8349               ip1 = j+sz;
8350             }
8351           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8352           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8353           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8354         }
8355       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8356     }
8357   return (ret>0.);
8358 }
8359
8360 /*!
8361  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8362  */
8363 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8364 {
8365   std::vector<std::pair<int,int> > edges;
8366   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8367   const int *bgFace=begin;
8368   for(std::size_t i=0;i<nbOfFaces;i++)
8369     {
8370       const int *endFace=std::find(bgFace+1,end,-1);
8371       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8372       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8373         {
8374           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8375           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8376             return false;
8377           edges.push_back(p1);
8378         }
8379       bgFace=endFace+1;
8380     }
8381   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8382 }
8383
8384 /*!
8385  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8386  */
8387 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8388 {
8389   double vec0[3],vec1[3];
8390   std::size_t sz=std::distance(begin,end);
8391   if(sz%2!=0)
8392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8393   int nbOfNodes=(int)sz/2;
8394   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8395   const double *pt0=coords+3*begin[0];
8396   const double *pt1=coords+3*begin[nbOfNodes];
8397   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8398   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8399 }
8400
8401 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8402 {
8403   std::size_t sz=std::distance(begin,end);
8404   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8405   std::size_t nbOfNodes(sz/2);
8406   std::copy(begin,end,(int *)tmp);
8407   for(std::size_t j=1;j<nbOfNodes;j++)
8408     {
8409       begin[j]=tmp[nbOfNodes-j];
8410       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8411     }
8412 }
8413
8414 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8415 {
8416   std::size_t sz=std::distance(begin,end);
8417   if(sz!=4)
8418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8419   double vec0[3],vec1[3];
8420   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8421   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]; 
8422   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;
8423 }
8424
8425 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8426 {
8427   std::size_t sz=std::distance(begin,end);
8428   if(sz!=5)
8429     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8430   double vec0[3];
8431   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8432   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8433   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8434 }
8435
8436 /*!
8437  * 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 ) 
8438  * 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
8439  * a 2D space.
8440  *
8441  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8442  * \param [in] coords the coordinates with nb of components exactly equal to 3
8443  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8444  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8445  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8446  */
8447 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8448 {
8449   int nbFaces=std::count(begin+1,end,-1)+1;
8450   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8451   double *vPtr=v->getPointer();
8452   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8453   double *pPtr=p->getPointer();
8454   const int *stFaceConn=begin+1;
8455   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8456     {
8457       const int *endFaceConn=std::find(stFaceConn,end,-1);
8458       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8459       stFaceConn=endFaceConn+1;
8460     }
8461   pPtr=p->getPointer(); vPtr=v->getPointer();
8462   DataArrayInt *comm1=0,*commI1=0;
8463   v->findCommonTuples(eps,-1,comm1,commI1);
8464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8465   const int *comm1Ptr=comm1->getConstPointer();
8466   const int *commI1Ptr=commI1->getConstPointer();
8467   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8468   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8469   //
8470   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8471   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8472   mm->finishInsertingCells();
8473   //
8474   for(int i=0;i<nbOfGrps1;i++)
8475     {
8476       int vecId=comm1Ptr[commI1Ptr[i]];
8477       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8478       DataArrayInt *comm2=0,*commI2=0;
8479       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8480       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8481       const int *comm2Ptr=comm2->getConstPointer();
8482       const int *commI2Ptr=commI2->getConstPointer();
8483       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8484       for(int j=0;j<nbOfGrps2;j++)
8485         {
8486           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8487             {
8488               res->insertAtTheEnd(begin,end);
8489               res->pushBackSilent(-1);
8490             }
8491           else
8492             {
8493               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8494               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8495               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8496               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8497               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8498               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8499               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8500               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8501               const int *idsNodePtr=idsNode->getConstPointer();
8502               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];
8503               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8504               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8505               if(std::abs(norm)>eps)
8506                 {
8507                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8508                   mm3->rotate(center,vec,angle);
8509                 }
8510               mm3->changeSpaceDimension(2);
8511               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8512               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8513               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8514               int nbOfCells=mm4->getNumberOfCells();
8515               for(int k=0;k<nbOfCells;k++)
8516                 {
8517                   int l=0;
8518                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8519                     res->pushBackSilent(idsNodePtr[*work]);
8520                   res->pushBackSilent(-1);
8521                 }
8522             }
8523         }
8524     }
8525   res->popBackSilent();
8526 }
8527
8528 /*!
8529  * 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
8530  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8531  * 
8532  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8533  * \param [in] coords coordinates expected to have 3 components.
8534  * \param [in] begin start of the nodal connectivity of the face.
8535  * \param [in] end end of the nodal connectivity (excluded) of the face.
8536  * \param [out] v the normalized vector of size 3
8537  * \param [out] p the pos of plane
8538  */
8539 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8540 {
8541   std::size_t nbPoints=std::distance(begin,end);
8542   if(nbPoints<3)
8543     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8544   double vec[3]={0.,0.,0.};
8545   std::size_t j=0;
8546   bool refFound=false;
8547   for(;j<nbPoints-1 && !refFound;j++)
8548     {
8549       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8550       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8551       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8552       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8553       if(norm>eps)
8554         {
8555           refFound=true;
8556           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8557         }
8558     }
8559   for(std::size_t i=j;i<nbPoints-1;i++)
8560     {
8561       double curVec[3];
8562       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8563       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8564       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8565       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8566       if(norm<eps)
8567         continue;
8568       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8569       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];
8570       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8571       if(norm>eps)
8572         {
8573           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8574           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8575           return ;
8576         }
8577     }
8578   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8579 }
8580
8581 /*!
8582  * This method tries to obtain a well oriented polyhedron.
8583  * If the algorithm fails, an exception will be thrown.
8584  */
8585 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8586 {
8587   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8588   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8589   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8590   isPerm[0]=true;
8591   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8592   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8593   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8594   //
8595   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8596     {
8597       bgFace=begin;
8598       std::size_t smthChanged=0;
8599       for(std::size_t i=0;i<nbOfFaces;i++)
8600         {
8601           endFace=std::find(bgFace+1,end,-1);
8602           nbOfEdgesInFace=std::distance(bgFace,endFace);
8603           if(!isPerm[i])
8604             {
8605               bool b;
8606               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8607                 {
8608                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8609                   std::pair<int,int> p2(p1.second,p1.first);
8610                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8611                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8612                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8613                 }
8614               if(isPerm[i])
8615                 { 
8616                   if(!b)
8617                     std::reverse(bgFace+1,endFace);
8618                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8619                     {
8620                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8621                       std::pair<int,int> p2(p1.second,p1.first);
8622                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8623                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8624                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8625                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8626                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8627                       if(it!=edgesOK.end())
8628                         {
8629                           edgesOK.erase(it);
8630                           edgesFinished.push_back(p1);
8631                         }
8632                       else
8633                         edgesOK.push_back(p1);
8634                     }
8635                 }
8636             }
8637           bgFace=endFace+1;
8638         }
8639       if(smthChanged==0)
8640         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8641     }
8642   if(!edgesOK.empty())
8643     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8644   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8645     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8646       bgFace=begin;
8647       for(std::size_t i=0;i<nbOfFaces;i++)
8648         {
8649           endFace=std::find(bgFace+1,end,-1);
8650           std::reverse(bgFace+1,endFace);
8651           bgFace=endFace+1;
8652         }
8653     }
8654 }
8655
8656 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8657 {
8658   int nbOfNodesExpected(skin->getNumberOfNodes());
8659   const int *n2oPtr(n2o->getConstPointer());
8660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8661   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8662   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8663   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8664   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8665   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8666   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8667   if(nbOfNodesExpected<1)
8668     return ret.retn();
8669   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8670   *work++=n2oPtr[prevNode];
8671   for(int i=1;i<nbOfNodesExpected;i++)
8672     {
8673       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8674         {
8675           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8676           conn.erase(prevNode);
8677           if(conn.size()==1)
8678             {
8679               int curNode(*(conn.begin()));
8680               *work++=n2oPtr[curNode];
8681               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8682               shar.erase(prevCell);
8683               if(shar.size()==1)
8684                 {
8685                   prevCell=*(shar.begin());
8686                   prevNode=curNode;
8687                 }
8688               else
8689                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8690             }
8691           else
8692             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8693         }
8694       else
8695         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8696     }
8697   return ret.retn();
8698 }
8699
8700 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8701 {
8702   int nbOfNodesExpected(skin->getNumberOfNodes());
8703   int nbOfTurn(nbOfNodesExpected/2);
8704   const int *n2oPtr(n2o->getConstPointer());
8705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8706   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8707   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8708   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8709   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8711   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8712   if(nbOfNodesExpected<1)
8713     return ret.retn();
8714   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8715   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8716   for(int i=1;i<nbOfTurn;i++)
8717     {
8718       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8719         {
8720           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8721           conn.erase(prevNode);
8722           if(conn.size()==1)
8723             {
8724               int curNode(*(conn.begin()));
8725               *work=n2oPtr[curNode];
8726               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8727               shar.erase(prevCell);
8728               if(shar.size()==1)
8729                 {
8730                   int curCell(*(shar.begin()));
8731                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8732                   prevCell=curCell;
8733                   prevNode=curNode;
8734                   work++;
8735                 }
8736               else
8737                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8738             }
8739           else
8740             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8741         }
8742       else
8743         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8744     }
8745   return ret.retn();
8746 }
8747
8748 /*!
8749  * This method makes the assumption spacedimension == meshdimension == 2.
8750  * This method works only for linear cells.
8751  * 
8752  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8753  */
8754 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8755 {
8756   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8758   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8759   int oldNbOfNodes(skin->getNumberOfNodes());
8760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8761   int nbOfNodesExpected(skin->getNumberOfNodes());
8762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8763   int nbCells(skin->getNumberOfCells());
8764   if(nbCells==nbOfNodesExpected)
8765     return buildUnionOf2DMeshLinear(skin,n2o);
8766   else if(2*nbCells==nbOfNodesExpected)
8767     return buildUnionOf2DMeshQuadratic(skin,n2o);
8768   else
8769     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8770 }
8771
8772 /*!
8773  * This method makes the assumption spacedimension == meshdimension == 3.
8774  * This method works only for linear cells.
8775  * 
8776  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8777  */
8778 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8779 {
8780   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8782   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8783   const int *conn=m->getNodalConnectivity()->getConstPointer();
8784   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8785   int nbOfCells=m->getNumberOfCells();
8786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8787   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8788   if(nbOfCells<1)
8789     return ret.retn();
8790   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8791   for(int i=1;i<nbOfCells;i++)
8792     {
8793       *work++=-1;
8794       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8795     }
8796   return ret.retn();
8797 }
8798
8799 /*!
8800  * \brief Creates a graph of cell neighbors
8801  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8802  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8803  *  For example
8804  *  - index:  0 3 5 6 6
8805  *  - value:  1 2 3 2 3 3
8806  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8807  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8808  */
8809 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8810 {
8811   checkConnectivityFullyDefined();
8812
8813   int meshDim = this->getMeshDimension();
8814   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8815   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8816   this->getReverseNodalConnectivity(revConn,indexr);
8817   const int* indexr_ptr=indexr->getConstPointer();
8818   const int* revConn_ptr=revConn->getConstPointer();
8819
8820   const ParaMEDMEM::DataArrayInt* index;
8821   const ParaMEDMEM::DataArrayInt* conn;
8822   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8823   index=this->getNodalConnectivityIndex();
8824   int nbCells=this->getNumberOfCells();
8825   const int* index_ptr=index->getConstPointer();
8826   const int* conn_ptr=conn->getConstPointer();
8827
8828   //creating graph arcs (cell to cell relations)
8829   //arcs are stored in terms of (index,value) notation
8830   // 0 3 5 6 6
8831   // 1 2 3 2 3 3
8832   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8833   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8834
8835   //warning here one node have less than or equal effective number of cell with it
8836   //but cell could have more than effective nodes
8837   //because other equals nodes in other domain (with other global inode)
8838   std::vector <int> cell2cell_index(nbCells+1,0);
8839   std::vector <int> cell2cell;
8840   cell2cell.reserve(3*nbCells);
8841
8842   for (int icell=0; icell<nbCells;icell++)
8843     {
8844       std::map<int,int > counter;
8845       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8846         {
8847           int inode=conn_ptr[iconn];
8848           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8849             {
8850               int icell2=revConn_ptr[iconnr];
8851               std::map<int,int>::iterator iter=counter.find(icell2);
8852               if (iter!=counter.end()) (iter->second)++;
8853               else counter.insert(std::make_pair(icell2,1));
8854             }
8855         }
8856       for (std::map<int,int>::const_iterator iter=counter.begin();
8857            iter!=counter.end(); iter++)
8858         if (iter->second >= meshDim)
8859           {
8860             cell2cell_index[icell+1]++;
8861             cell2cell.push_back(iter->first);
8862           }
8863     }
8864   indexr->decrRef();
8865   revConn->decrRef();
8866   cell2cell_index[0]=0;
8867   for (int icell=0; icell<nbCells;icell++)
8868     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8869
8870   //filling up index and value to create skylinearray structure
8871   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8872   return array;
8873 }
8874
8875 /*!
8876  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8877  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8878  */
8879 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8880 {
8881   double *w=zipFrmt;
8882   if(spaceDim==3)
8883     for(int i=0;i<nbOfNodesInCell;i++)
8884       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8885   else if(spaceDim==2)
8886     {
8887       for(int i=0;i<nbOfNodesInCell;i++)
8888         {
8889           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8890           *w++=0.;
8891         }
8892     }
8893   else
8894     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8895 }
8896
8897 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8898 {
8899   int nbOfCells=getNumberOfCells();
8900   if(nbOfCells<=0)
8901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8902   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};
8903   ofs << "  <" << getVTKDataSetType() << ">\n";
8904   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8905   ofs << "      <PointData>\n" << pointData << std::endl;
8906   ofs << "      </PointData>\n";
8907   ofs << "      <CellData>\n" << cellData << std::endl;
8908   ofs << "      </CellData>\n";
8909   ofs << "      <Points>\n";
8910   if(getSpaceDimension()==3)
8911     _coords->writeVTK(ofs,8,"Points",byteData);
8912   else
8913     {
8914       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8915       coo->writeVTK(ofs,8,"Points",byteData);
8916     }
8917   ofs << "      </Points>\n";
8918   ofs << "      <Cells>\n";
8919   const int *cPtr=_nodal_connec->getConstPointer();
8920   const int *cIPtr=_nodal_connec_index->getConstPointer();
8921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8925   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8926   int szFaceOffsets=0,szConn=0;
8927   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8928     {
8929       *w2=cPtr[cIPtr[i]];
8930       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8931         {
8932           *w1=-1;
8933           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8934           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8935         }
8936       else
8937         {
8938           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8939           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8940           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8941           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8942           w4=std::copy(c.begin(),c.end(),w4);
8943         }
8944     }
8945   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8946   types->writeVTK(ofs,8,"UInt8","types",byteData);
8947   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8948   if(szFaceOffsets!=0)
8949     {//presence of Polyhedra
8950       connectivity->reAlloc(szConn);
8951       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8952       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8953       w1=faces->getPointer();
8954       for(int i=0;i<nbOfCells;i++)
8955         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8956           {
8957             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8958             *w1++=nbFaces;
8959             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8960             for(int j=0;j<nbFaces;j++)
8961               {
8962                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8963                 *w1++=(int)std::distance(w6,w5);
8964                 w1=std::copy(w6,w5,w1);
8965                 w6=w5+1;
8966               }
8967           }
8968       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8969     }
8970   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8971   ofs << "      </Cells>\n";
8972   ofs << "    </Piece>\n";
8973   ofs << "  </" << getVTKDataSetType() << ">\n";
8974 }
8975
8976 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8977 {
8978   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8979   if(_mesh_dim==-2)
8980     { stream << " Not set !"; return ; }
8981   stream << " Mesh dimension : " << _mesh_dim << ".";
8982   if(_mesh_dim==-1)
8983     return ;
8984   if(!_coords)
8985     { stream << " No coordinates set !"; return ; }
8986   if(!_coords->isAllocated())
8987     { stream << " Coordinates set but not allocated !"; return ; }
8988   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8989   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8990   if(!_nodal_connec_index)
8991     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8992   if(!_nodal_connec_index->isAllocated())
8993     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8994   int lgth=_nodal_connec_index->getNumberOfTuples();
8995   int cpt=_nodal_connec_index->getNumberOfComponents();
8996   if(cpt!=1 || lgth<1)
8997     return ;
8998   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8999 }
9000
9001 std::string MEDCouplingUMesh::getVTKDataSetType() const
9002 {
9003   return std::string("UnstructuredGrid");
9004 }
9005
9006 std::string MEDCouplingUMesh::getVTKFileExtension() const
9007 {
9008   return std::string("vtu");
9009 }
9010
9011 /*!
9012  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9013  * returns a result mesh constituted by polygons.
9014  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9015  * all nodes from m2.
9016  * The meshes should be in 2D space. In
9017  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9018  * meshes.
9019  *  \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
9020  *                      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)
9021  *  \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
9022  *                      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)
9023  *  \param [in] eps - precision used to detect coincident mesh entities.
9024  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9025  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9026  *         this array using decrRef() as it is no more needed.
9027  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9028  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9029  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9030  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9031  *         it is no more needed.  
9032  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9033  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9034  *         is no more needed.  
9035  *  \throw If the coordinates array is not set in any of the meshes.
9036  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9037  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9038  *
9039  *  \sa conformize2D, mergeNodes
9040  */
9041 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9042                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9043 {
9044   if(!m1 || !m2)
9045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9046   m1->checkFullyDefined();
9047   m2->checkFullyDefined();
9048   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9050
9051   // Step 1: compute all edge intersections (new nodes)
9052   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9053   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9054   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9055   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9056   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9057                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9058                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9059   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9061   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9062
9063   // Step 2: re-order newly created nodes according to the ordering found in m2
9064   std::vector< std::vector<int> > intersectEdge2;
9065   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9066   subDiv2.clear(); dd5=0; dd6=0;
9067
9068   // Step 3:
9069   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9070   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9071   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9072                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9073
9074   // Step 4: Prepare final result:
9075   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9076   addCooDa->alloc((int)(addCoo.size())/2,2);
9077   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9078   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9079   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9080   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9081   std::vector<const DataArrayDouble *> coordss(4);
9082   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9083   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9084   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9086   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9087   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9088   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9089   ret->setConnectivity(conn,connI,true);
9090   ret->setCoords(coo);
9091   cellNb1=c1.retn(); cellNb2=c2.retn();
9092   return ret.retn();
9093 }
9094
9095 /// @cond INTERNAL
9096
9097 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9098 {
9099   if(candidates.empty())
9100     return false;
9101   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9102     {
9103       const std::vector<int>& pool(intersectEdge1[*it]);
9104       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9105       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9106         {
9107           retVal=*it+1;
9108           return true;
9109         }
9110       tmp[0]=stop; tmp[1]=start;
9111       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9112         {
9113           retVal=-*it-1;
9114           return true;
9115         }
9116     }
9117   return false;
9118 }
9119
9120 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,
9121                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9122 {
9123   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9124   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9125   int nCells(mesh1D->getNumberOfCells());
9126   if(nCells!=(int)intersectEdge2.size())
9127     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9128   const DataArrayDouble *coo2(mesh1D->getCoords());
9129   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9130   const double *coo2Ptr(coo2->begin());
9131   int offset1(coords1->getNumberOfTuples());
9132   int offset2(offset1+coo2->getNumberOfTuples());
9133   int offset3(offset2+addCoo.size()/2);
9134   std::vector<double> addCooQuad;
9135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9136   int tmp[4],cicnt(0),kk(0);
9137   for(int i=0;i<nCells;i++)
9138     {
9139       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9140       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9141       const std::vector<int>& subEdges(intersectEdge2[i]);
9142       int nbSubEdge(subEdges.size()/2);
9143       for(int j=0;j<nbSubEdge;j++,kk++)
9144         {
9145           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
9146           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9147           INTERP_KERNEL::Edge *e2Ptr(e2);
9148           std::map<int,int>::const_iterator itm;
9149           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9150             {
9151               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9152               itm=mergedNodes.find(subEdges[2*j]);
9153               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9154               itm=mergedNodes.find(subEdges[2*j+1]);
9155               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9156               tmp[3]=offset3+(int)addCooQuad.size()/2;
9157               double tmp2[2];
9158               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9159               cicnt+=4;
9160               cOut->insertAtTheEnd(tmp,tmp+4);
9161               ciOut->pushBackSilent(cicnt);
9162             }
9163           else
9164             {
9165               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9166               itm=mergedNodes.find(subEdges[2*j]);
9167               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9168               itm=mergedNodes.find(subEdges[2*j+1]);
9169               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9170               cicnt+=3;
9171               cOut->insertAtTheEnd(tmp,tmp+3);
9172               ciOut->pushBackSilent(cicnt);
9173             }
9174           int tmp00;
9175           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9176             {
9177               idsInRetColinear->pushBackSilent(kk);
9178               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9179             }
9180         }
9181       e->decrRef();
9182     }
9183   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9184   ret->setConnectivity(cOut,ciOut,true);
9185   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9186   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9187   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9188   std::vector<const DataArrayDouble *> coordss(4);
9189   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9190   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9191   ret->setCoords(arr);
9192   return ret.retn();
9193 }
9194
9195 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9196 {
9197   std::vector<int> allEdges;
9198   for(const int *it2(descBg);it2!=descEnd;it2++)
9199     {
9200       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9201       if(*it2>0)
9202         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9203       else
9204         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9205     }
9206   std::size_t nb(allEdges.size());
9207   if(nb%2!=0)
9208     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9209   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9210   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9211   ret->setCoords(coords);
9212   ret->allocateCells(1);
9213   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9214   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9215     connOut[kk]=allEdges[2*kk];
9216   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9217   return ret.retn();
9218 }
9219
9220 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9221 {
9222   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9223   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9224   std::size_t ii(0);
9225   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9226   if(sz!=std::distance(descBg,descEnd))
9227     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9228   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9229   std::vector<int> allEdges,centers;
9230   const double *coordsPtr(coords->begin());
9231   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9232   int offset(coords->getNumberOfTuples());
9233   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9234     {
9235       INTERP_KERNEL::NormalizedCellType typeOfSon;
9236       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9237       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9238       if(*it2>0)
9239         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9240       else
9241         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9242       if(edge1.size()==2)
9243         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9244       else
9245         {//the current edge has been subsplit -> create corresponding centers.
9246           std::size_t nbOfCentersToAppend(edge1.size()/2);
9247           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9248           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9249           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9250           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9251             {
9252               double tmpp[2];
9253               const double *aa(coordsPtr+2*(*it3++));
9254               const double *bb(coordsPtr+2*(*it3++));
9255               ee->getMiddleOfPoints(aa,bb,tmpp);
9256               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9257               centers.push_back(offset+k);
9258             }
9259         }
9260     }
9261   std::size_t nb(allEdges.size());
9262   if(nb%2!=0)
9263     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9264   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9265   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9266   if(addCoo->empty())
9267     ret->setCoords(coords);
9268   else
9269     {
9270       addCoo->rearrange(2);
9271       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9272       ret->setCoords(addCoo);
9273     }
9274   ret->allocateCells(1);
9275   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9276   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9277     connOut[kk]=allEdges[2*kk];
9278   connOut.insert(connOut.end(),centers.begin(),centers.end());
9279   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9280   return ret.retn();
9281 }
9282
9283 /*!
9284  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9285  * of those edges.
9286  *
9287  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9288  */
9289 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9290 {
9291   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9292   if(!cm.isQuadratic())
9293     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9294   else
9295     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9296 }
9297
9298 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9299 {
9300   bool isQuad(false);
9301   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9302     {
9303       const INTERP_KERNEL::Edge *ee(*it);
9304       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9305         isQuad=true;
9306     }
9307   if(!isQuad)
9308     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9309   else
9310     {
9311       const double *coo(mesh2D->getCoords()->begin());
9312       std::size_t sz(conn.size());
9313       std::vector<double> addCoo;
9314       std::vector<int> conn2(conn);
9315       int offset(mesh2D->getNumberOfNodes());
9316       for(std::size_t i=0;i<sz;i++)
9317         {
9318           double tmp[2];
9319           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9320           addCoo.insert(addCoo.end(),tmp,tmp+2);
9321           conn2.push_back(offset+(int)i);
9322         }
9323       mesh2D->getCoords()->rearrange(1);
9324       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9325       mesh2D->getCoords()->rearrange(2);
9326       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9327     }
9328 }
9329
9330 /*!
9331  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9332  *
9333  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9334  * a set of edges defined in \a splitMesh1D.
9335  */
9336 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9337                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9338 {
9339   std::size_t nb(edge1Bis.size()/2);
9340   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9341   int iEnd(splitMesh1D->getNumberOfCells());
9342   if(iEnd==0)
9343     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9344   std::size_t ii,jj;
9345   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9346   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9347   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9348   //
9349   if(jj==nb)
9350     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9351       out0.resize(1); out1.resize(1);
9352       std::vector<int>& connOut(out0[0]);
9353       connOut.resize(nbOfEdgesOf2DCellSplit);
9354       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9355       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9356       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9357         {
9358           connOut[kk]=edge1Bis[2*kk];
9359           edgesPtr[kk]=edge1BisPtr[2*kk];
9360         }
9361     }
9362   else
9363     {
9364       // [i,iEnd[ contains the
9365       out0.resize(2); out1.resize(2);
9366       std::vector<int>& connOutLeft(out0[0]);
9367       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9368       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9369       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9370       for(std::size_t k=ii;k<jj+1;k++)
9371         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9372       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9373       for(int ik=0;ik<iEnd;ik++)
9374         {
9375           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9376           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9377           ees[ik]=ee;
9378         }
9379       for(int ik=iEnd-1;ik>=0;ik--)
9380         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9381       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9382         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9383       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9384       for(int ik=0;ik<iEnd;ik++)
9385         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9386       eright.insert(eright.end(),ees.begin(),ees.end());
9387     }
9388 }
9389
9390 /// @endcond
9391
9392 /// @cond INTERNAL
9393
9394 struct CellInfo
9395 {
9396 public:
9397   CellInfo() { }
9398   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9399 public:
9400   std::vector<int> _edges;
9401   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9402 };
9403
9404 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9405 {
9406   std::size_t nbe(edges.size());
9407   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9408   for(std::size_t i=0;i<nbe;i++)
9409     {
9410       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9411       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9412     }
9413   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9414   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9415   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9416 }
9417
9418 class EdgeInfo
9419 {
9420 public:
9421   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9422   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9423   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9424   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9425   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9426 private:
9427   int _istart;
9428   int _iend;
9429   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9430   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9431   int _left;
9432   int _right;
9433 };
9434
9435 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9436 {
9437   const MEDCouplingUMesh *mesh(_mesh);
9438   if(mesh)
9439     return ;
9440   if(_right<pos)
9441     return ;
9442   if(_left>pos)
9443     { _left++; _right++; return ; }
9444   if(_right==pos)
9445     {
9446       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9447       if((isLeft && isRight) || (!isLeft && !isRight))
9448         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9449       if(isLeft)
9450         return ;
9451       if(isRight)
9452         {
9453           _right++;
9454           return ;
9455         }
9456     }
9457   if(_left==pos)
9458     {
9459       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9460       if((isLeft && isRight) || (!isLeft && !isRight))
9461         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9462       if(isLeft)
9463         {
9464           _right++;
9465           return ;
9466         }
9467       if(isRight)
9468         {
9469           _left++;
9470           _right++;
9471           return ;
9472         }
9473     }
9474 }
9475
9476 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9477 {
9478   const MEDCouplingUMesh *mesh(_mesh);
9479   if(!mesh)
9480     {
9481       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9482     }
9483   else
9484     {// not fully splitting cell case
9485       if(mesh2D->getNumberOfCells()==1)
9486         {//little optimization. 1 cell no need to find in which cell mesh is !
9487           neighbors[0]=offset; neighbors[1]=offset;
9488           return;
9489         }
9490       else
9491         {
9492           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9493           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9494           if(cellId==-1)
9495             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9496           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9497         }
9498     }
9499 }
9500
9501 class VectorOfCellInfo
9502 {
9503 public:
9504   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9505   std::size_t size() const { return _pool.size(); }
9506   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9507   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9508   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9509   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9510   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9511   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9512 private:
9513   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9514   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9515   const CellInfo& get(int pos) const;
9516   CellInfo& get(int pos);
9517 private:
9518   std::vector<CellInfo> _pool;
9519   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9520   std::vector<EdgeInfo> _edge_info;
9521 };
9522
9523 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9524 {
9525   _pool[0]._edges=edges;
9526   _pool[0]._edges_ptr=edgesPtr;
9527 }
9528
9529 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9530 {
9531   if(_pool.empty())
9532     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9533   if(_pool.size()==1)
9534     return 0;
9535   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9536   if(!zeMesh)
9537     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9538   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9539   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9540 }
9541
9542 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9543 {
9544   get(pos);//to check pos
9545   bool isFast(pos==0 && _pool.size()==1);
9546   std::size_t sz(edges.size());
9547   // dealing with edges
9548   if(sz==1)
9549     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9550   else
9551     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9552   //
9553   std::vector<CellInfo> pool(_pool.size()-1+sz);
9554   for(int i=0;i<pos;i++)
9555     pool[i]=_pool[i];
9556   for(std::size_t j=0;j<sz;j++)
9557     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9558   for(int i=pos+1;i<(int)_pool.size();i++)
9559     pool[i+sz-1]=_pool[i];
9560   _pool=pool;
9561   //
9562   if(sz==2)
9563     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9564   //
9565   if(isFast)
9566     {
9567       _ze_mesh=mesh;
9568       return ;
9569     }
9570   //
9571   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9572   if(pos>0)
9573     {
9574       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9575       ms.push_back(elt);
9576     }
9577   ms.push_back(mesh);
9578   if(pos<_ze_mesh->getNumberOfCells()-1)
9579   {
9580     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9581     ms.push_back(elt);
9582   }
9583   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9584   for(std::size_t j=0;j<ms2.size();j++)
9585     ms2[j]=ms[j];
9586   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9587 }
9588
9589 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9590 {
9591   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9592 }
9593
9594 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9595 {
9596   if(pos<0)
9597     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9598   int ret(0);
9599   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9600     {
9601       if((*it).isInMyRange(pos))
9602         return ret;
9603     }
9604   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9605 }
9606
9607 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9608 {
9609   get(pos);//to check;
9610   if(_edge_info.empty())
9611     return ;
9612   std::size_t sz(_edge_info.size()-1);
9613   for(std::size_t i=0;i<sz;i++)
9614     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9615 }
9616
9617 const CellInfo& VectorOfCellInfo::get(int pos) const
9618 {
9619   if(pos<0 || pos>=(int)_pool.size())
9620     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9621   return _pool[pos];
9622 }
9623
9624 CellInfo& VectorOfCellInfo::get(int pos)
9625 {
9626   if(pos<0 || pos>=(int)_pool.size())
9627     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9628   return _pool[pos];
9629 }
9630
9631 /*!
9632  * Given :
9633  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9634  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9635  *
9636  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9637  *
9638  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9639  *
9640  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9641  */
9642 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9643                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9644 {
9645   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9646   if(nbCellsInSplitMesh1D==0)
9647     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9648   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9649   std::size_t nb(allEdges.size()),jj;
9650   if(nb%2!=0)
9651     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9652   std::vector<int> edge1Bis(nb*2);
9653   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9654   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9655   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9656   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9657   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9658   //
9659   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9660   int *idsLeftRightPtr(idsLeftRight->getPointer());
9661   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9662   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9663     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9664       int iEnd(iStart);
9665       for(;iEnd<nbCellsInSplitMesh1D;)
9666         {
9667           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9668           if(jj!=nb)
9669             break;
9670           else
9671             iEnd++;
9672         }
9673       if(iEnd<nbCellsInSplitMesh1D)
9674         iEnd++;
9675       //
9676       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9677       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9678       //
9679       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9680       retTmp->setCoords(splitMesh1D->getCoords());
9681       retTmp->allocateCells();
9682
9683       std::vector< std::vector<int> > out0;
9684       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9685
9686       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9687       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9688         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9689       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9690       //
9691       iStart=iEnd;
9692     }
9693   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9694     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9695   return pool.getZeMesh().retn();
9696 }
9697
9698 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9699                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9700                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9701 {
9702   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9703   //
9704   std::vector<int> allEdges;
9705   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9706   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9707     {
9708       int edgeId(std::abs(*it)-1);
9709       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9710       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9711       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9712       if(*it>0)
9713         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9714       else
9715         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9716       std::size_t sz(edge1.size());
9717       for(std::size_t cnt=0;cnt<sz;cnt++)
9718         allEdgesPtr.push_back(ee);
9719     }
9720   //
9721   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9722 }
9723
9724 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9725 {
9726   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9727     {//easy case comparison not
9728       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9729     }
9730   else if(typ1.isQuadratic() && typ2.isQuadratic())
9731     {
9732       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9733       if(!status0)
9734         return false;
9735       if(conn1[2]==conn2[2])
9736         return true;
9737       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9738       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9739       return dist<eps;
9740     }
9741   else
9742     {//only one is quadratic
9743       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9744       if(!status0)
9745         return false;
9746       const double *a(0),*bb(0),*be(0);
9747       if(typ1.isQuadratic())
9748         {
9749           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9750         }
9751       else
9752         {
9753           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9754         }
9755       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9756       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9757       return dist<eps;
9758     }
9759 }
9760
9761 /*!
9762  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9763  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9764  *
9765  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9766  */
9767 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9768 {
9769   if(candidatesIn2DEnd==candidatesIn2DBg)
9770     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9771   const double *coo(mesh2DSplit->getCoords()->begin());
9772   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9773     return *candidatesIn2DBg;
9774   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9775   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9776   if(cellIdInMesh1DSplitRelative<0)
9777     cur1D->changeOrientationOfCells();
9778   const int *c1D(cur1D->getNodalConnectivity()->begin());
9779   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9780   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9781     {
9782       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9783       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9784       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9785       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9786       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9787       for(unsigned it2=0;it2<sz;it2++)
9788         {
9789           INTERP_KERNEL::NormalizedCellType typeOfSon;
9790           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9791           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9792           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9793             return *it;
9794         }
9795     }
9796   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9797 }
9798
9799 /// @endcond
9800
9801 /*!
9802  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9803  * 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
9804  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9805  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9806  *
9807  * \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
9808  *                      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)
9809  * \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
9810  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9811  * \param [in] eps - precision used to perform intersections and localization operations.
9812  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9813  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9814  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9815  *                               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.
9816  * \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
9817  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9818  *                               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.
9819  *
9820  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9821  */
9822 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9823 {
9824   if(!mesh2D || !mesh1D)
9825     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9826   mesh2D->checkFullyDefined();
9827   mesh1D->checkFullyDefined();
9828   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9829   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9830     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9831   // Step 1: compute all edge intersections (new nodes)
9832   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9833   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9834   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9835   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9836   //
9837   // Build desc connectivity
9838   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9840   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9841   std::map<int,int> mergedNodes;
9842   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9843   // use mergeNodes to fix intersectEdge1
9844   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9845     {
9846       std::size_t n((*it0).size()/2);
9847       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9848       std::map<int,int>::const_iterator it1;
9849       it1=mergedNodes.find(eltStart);
9850       if(it1!=mergedNodes.end())
9851         (*it0)[0]=(*it1).second;
9852       it1=mergedNodes.find(eltEnd);
9853       if(it1!=mergedNodes.end())
9854         (*it0)[2*n-1]=(*it1).second;
9855     }
9856   //
9857   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9858   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9859   // Step 2: re-order newly created nodes according to the ordering found in m2
9860   std::vector< std::vector<int> > intersectEdge2;
9861   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9862   subDiv2.clear();
9863   // Step 3: compute splitMesh1D
9864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9866   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9867       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9869   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9870   // deal with cells in mesh2D that are not cut but only some of their edges are
9871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9872   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9873   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9875   if(!idsInDesc2DToBeRefined->empty())
9876     {
9877       DataArrayInt *out0(0),*outi0(0);
9878       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9879       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9880       out0s=out0;
9881       out0s=out0s->buildUnique();
9882       out0s->sort(true);
9883     }
9884   //
9885   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9886   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9888   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9890   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9891   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9892     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9895   if((DataArrayInt *)out0s)
9896     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9897   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9898   // OK all is ready to insert in ret2 mesh
9899   if(!untouchedCells->empty())
9900     {// the most easy part, cells in mesh2D not impacted at all
9901       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9902       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9903       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9904     }
9905   if((DataArrayInt *)out0s)
9906     {// here dealing with cells in out0s but not in cellsToBeModified
9907       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9908       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9909       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9910         {
9911           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9912           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9913         }
9914       int offset(ret2->getNumberOfTuples());
9915       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9916       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9917       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9918       int kk(0),*ret3ptr(partOfRet3->getPointer());
9919       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9920         {
9921           int faceId(std::abs(*it)-1);
9922           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9923             {
9924               int tmp(fewModifiedCells->locateValue(*it2));
9925               if(tmp!=-1)
9926                 {
9927                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9928                     ret3ptr[2*kk]=tmp+offset;
9929                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9930                     ret3ptr[2*kk+1]=tmp+offset;
9931                 }
9932               else
9933                 {//the current edge is shared by a 2D cell that will be split just after
9934                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9935                     ret3ptr[2*kk]=-(*it2+1);
9936                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9937                     ret3ptr[2*kk+1]=-(*it2+1);
9938                 }
9939             }
9940         }
9941       m1Desc->setCoords(ret1->getCoords());
9942       ret1NonCol->setCoords(ret1->getCoords());
9943       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9944       if(!outMesh2DSplit.empty())
9945         {
9946           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9947           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9948             (*itt)->setCoords(da);
9949         }
9950     }
9951   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9952   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9953     {
9954       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9955       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9956       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9957       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9958       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9959       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9960       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9961       outMesh2DSplit.push_back(splitOfOneCell);
9962       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9963         ret2->pushBackSilent(*it);
9964     }
9965   //
9966   std::size_t nbOfMeshes(outMesh2DSplit.size());
9967   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9968   for(std::size_t i=0;i<nbOfMeshes;i++)
9969     tmp[i]=outMesh2DSplit[i];
9970   //
9971   ret1->getCoords()->setInfoOnComponents(compNames);
9972   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9973   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9974   ret3->rearrange(1);
9975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9976   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9977     {
9978       int old2DCellId(-ret3->getIJ(*it,0)-1);
9979       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9980       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
9981     }
9982   ret3->changeValue(std::numeric_limits<int>::max(),-1);
9983   ret3->rearrange(2);
9984   //
9985   splitMesh1D=ret1.retn();
9986   splitMesh2D=ret2D.retn();
9987   cellIdInMesh2D=ret2.retn();
9988   cellIdInMesh1D=ret3.retn();
9989 }
9990
9991 /**
9992  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9993  * (newly created) nodes corresponding to the edge intersections.
9994  * Output params:
9995  * @param[out] cr, crI connectivity of the resulting mesh
9996  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9997  * TODO: describe input parameters
9998  */
9999 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
10000                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
10001                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
10002                                                          const std::vector<double>& addCoords,
10003                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10004 {
10005   static const int SPACEDIM=2;
10006   const double *coo1(m1->getCoords()->getConstPointer());
10007   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
10008   int offset1(m1->getNumberOfNodes());
10009   const double *coo2(m2->getCoords()->getConstPointer());
10010   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
10011   int offset2(offset1+m2->getNumberOfNodes());
10012   int offset3(offset2+((int)addCoords.size())/2);
10013   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10014   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10015   // Here a BBTree on 2D-cells, not on segments:
10016   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10017   int ncell1(m1->getNumberOfCells());
10018   crI.push_back(0);
10019   for(int i=0;i<ncell1;i++)
10020     {
10021       std::vector<int> candidates2;
10022       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10023       std::map<INTERP_KERNEL::Node *,int> mapp;
10024       std::map<int,INTERP_KERNEL::Node *> mappRev;
10025       INTERP_KERNEL::QuadraticPolygon pol1;
10026       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10027       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10028       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10029       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10030       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10031       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10032           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10033       //
10034       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
10035       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10036       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10037       for(it1.first();!it1.finished();it1.next())
10038         edges1.insert(it1.current()->getPtr());
10039       //
10040       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10041       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10042       int ii=0;
10043       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10044         {
10045           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10046           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10047           // Complete mapping with elements coming from the current cell it2 in mesh2:
10048           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10049           // pol2 is the new QP in the final merged result.
10050           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10051               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10052         }
10053       ii=0;
10054       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10055         {
10056           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10057           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10058           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10059           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10060         }
10061       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10062       // by m2 but that we still want to keep in the final result.
10063       if(!edges1.empty())
10064         {
10065           try
10066           {
10067               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10068           }
10069           catch(INTERP_KERNEL::Exception& e)
10070           {
10071               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();
10072               throw INTERP_KERNEL::Exception(oss.str().c_str());
10073           }
10074         }
10075       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10076         (*it).second->decrRef();
10077     }
10078 }
10079
10080 /**
10081  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10082  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10083  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10084  * The caller is to deal with the resulting DataArrayInt.
10085  *  \throw If the coordinate array is not set.
10086  *  \throw If the nodal connectivity of the cells is not defined.
10087  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10088  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10089  *
10090  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10091  */
10092 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10093 {
10094   checkFullyDefined();
10095   if(getMeshDimension()!=1)
10096     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10097
10098   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10099   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10101   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10102   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10103   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10105   const int * dsi(_dsi->getConstPointer());
10106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10107   m_points=0;
10108   if (dsii->getNumberOfTuples())
10109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10110
10111   int nc(getNumberOfCells());
10112   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10113   result->alloc(nc,1);
10114
10115   // set of edges not used so far
10116   std::set<int> edgeSet;
10117   for (int i=0; i<nc; edgeSet.insert(i), i++);
10118
10119   int startSeg=0;
10120   int newIdx=0;
10121   // while we have points with only one neighbor segments
10122   do
10123     {
10124       std::list<int> linePiece;
10125       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10126       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10127         {
10128           // Fill the list forward (resp. backward) from the start segment:
10129           int activeSeg = startSeg;
10130           int prevPointId = -20;
10131           int ptId;
10132           while (!edgeSet.empty())
10133             {
10134               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10135                 {
10136                   if (direction==0)
10137                     linePiece.push_back(activeSeg);
10138                   else
10139                     linePiece.push_front(activeSeg);
10140                   edgeSet.erase(activeSeg);
10141                 }
10142
10143               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10144               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10145               if (dsi[ptId] == 1) // hitting the end of the line
10146                 break;
10147               prevPointId = ptId;
10148               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10149               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10150             }
10151         }
10152       // Done, save final piece into DA:
10153       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10154       newIdx += linePiece.size();
10155
10156       // identify next valid start segment (one which is not consumed)
10157       if(!edgeSet.empty())
10158         startSeg = *(edgeSet.begin());
10159     }
10160   while (!edgeSet.empty());
10161   return result.retn();
10162 }
10163
10164 /// @cond INTERNAL
10165
10166 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10167 {
10168   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10169   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10170   if(it==m.end())
10171     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10172   int v((*it).second);
10173   if(v==forbVal0 || v==forbVal1)
10174     return ;
10175   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10176     isect.push_back(v);
10177 }
10178
10179 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10180 {
10181   int sz(c.size());
10182   if(sz<=1)
10183     return false;
10184   bool presenceOfOn(false);
10185   for(int i=0;i<sz;i++)
10186     {
10187       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10188       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10189         continue ;
10190       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10191       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10192     }
10193   return presenceOfOn;
10194 }
10195
10196 /// @endcond
10197
10198 /**
10199  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10200  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10201  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10202  * a minimal creation of new nodes is wanted.
10203  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10204  * nodes if a SEG3 is split without information of middle.
10205  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10206  * avoid to have a non conform mesh.
10207  *
10208  * \return int - the number of new nodes created (in most of cases 0).
10209  * 
10210  * \throw If \a this is not coherent.
10211  * \throw If \a this has not spaceDim equal to 2.
10212  * \throw If \a this has not meshDim equal to 2.
10213  * \throw If some subcells needed to be split are orphan.
10214  * \sa MEDCouplingUMesh::conformize2D
10215  */
10216 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10217 {
10218   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10220   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10221   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10222     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10223   if(midOpt==0 && midOptI==0)
10224     {
10225       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10226       return 0;
10227     }
10228   else if(midOpt!=0 && midOptI!=0)
10229     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10230   else
10231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10232 }
10233
10234 /*!
10235  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10236  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10237  * 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
10238  * 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).
10239  * 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.
10240  * 
10241  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10242  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10243  *
10244  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10245  * This method expects that all nodes in \a this are not closer than \a eps.
10246  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10247  * 
10248  * \param [in] eps the relative error to detect merged edges.
10249  * \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
10250  *                           that the user is expected to deal with.
10251  *
10252  * \throw If \a this is not coherent.
10253  * \throw If \a this has not spaceDim equal to 2.
10254  * \throw If \a this has not meshDim equal to 2.
10255  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10256  */
10257 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10258 {
10259   static const int SPACEDIM=2;
10260   checkCoherency();
10261   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10264   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10265   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10266   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10267   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10268   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10269   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10270   std::vector<double> addCoo;
10271   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10272   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10273   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10274   for(int i=0;i<nDescCell;i++)
10275     {
10276       std::vector<int> candidates;
10277       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10278       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10279         if(*it>i)
10280           {
10281             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10282             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10283                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10284             INTERP_KERNEL::MergePoints merge;
10285             INTERP_KERNEL::QuadraticPolygon c1,c2;
10286             e1->intersectWith(e2,merge,c1,c2);
10287             e1->decrRef(); e2->decrRef();
10288             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10289               overlapEdge[i].push_back(*it);
10290             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10291               overlapEdge[*it].push_back(i);
10292           }
10293     }
10294   // splitting done. sort intersect point in intersectEdge.
10295   std::vector< std::vector<int> > middle(nDescCell);
10296   int nbOf2DCellsToBeSplit(0);
10297   bool middleNeedsToBeUsed(false);
10298   std::vector<bool> cells2DToTreat(nDescCell,false);
10299   for(int i=0;i<nDescCell;i++)
10300     {
10301       std::vector<int>& isect(intersectEdge[i]);
10302       int sz((int)isect.size());
10303       if(sz>1)
10304         {
10305           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10306           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10307           e->sortSubNodesAbs(coords,isect);
10308           e->decrRef();
10309         }
10310       if(sz!=0)
10311         {
10312           int idx0(rdi[i]),idx1(rdi[i+1]);
10313           if(idx1-idx0!=1)
10314             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10315           if(!cells2DToTreat[rd[idx0]])
10316             {
10317               cells2DToTreat[rd[idx0]]=true;
10318               nbOf2DCellsToBeSplit++;
10319             }
10320           // try to reuse at most eventual 'middle' of SEG3
10321           std::vector<int>& mid(middle[i]);
10322           mid.resize(sz+1,-1);
10323           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10324             {
10325               middleNeedsToBeUsed=true;
10326               const std::vector<int>& candidates(overlapEdge[i]);
10327               std::vector<int> trueCandidates;
10328               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10329                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10330                   trueCandidates.push_back(*itc);
10331               int stNode(c[ci[i]+1]),endNode(isect[0]);
10332               for(int j=0;j<sz+1;j++)
10333                 {
10334                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10335                     {
10336                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10337                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10338                         { mid[j]=*itc; break; }
10339                     }
10340                   stNode=endNode;
10341                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10342                 }
10343             }
10344         }
10345     }
10346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10347   if(nbOf2DCellsToBeSplit==0)
10348     return ret.retn();
10349   //
10350   int *retPtr(ret->getPointer());
10351   for(int i=0;i<nCell;i++)
10352     if(cells2DToTreat[i])
10353       *retPtr++=i;
10354   //
10355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10356   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10357   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10358   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10359   if(middleNeedsToBeUsed)
10360     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10361   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10362   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10363   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.
10364   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10365   {
10366     bool areNodesMerged; int newNbOfNodes;
10367     if(nbOfNodesCreated!=0)
10368       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10369   }
10370   return ret.retn();
10371 }
10372
10373 /*!
10374  * 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.
10375  * 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).
10376  * 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
10377  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10378  * 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
10379  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10380  *
10381  * 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
10382  * using new instance, idem for coordinates.
10383  *
10384  * 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.
10385  * 
10386  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10387  *
10388  * \throw If \a this is not coherent.
10389  * \throw If \a this has not spaceDim equal to 2.
10390  * \throw If \a this has not meshDim equal to 2.
10391  * 
10392  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10393  */
10394 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10395 {
10396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10397   checkCoherency();
10398   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10399     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10400   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10401   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10402   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10403   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10405   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10406   const double *coords(_coords->begin());
10407   int *newciptr(newci->getPointer());
10408   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10409     {
10410       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10411         ret->pushBackSilent(i);
10412       newciptr[1]=newc->getNumberOfTuples();
10413     }
10414   //
10415   if(ret->empty())
10416     return ret.retn();
10417   if(!appendedCoords->empty())
10418     {
10419       appendedCoords->rearrange(2);
10420       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10421       //non const part
10422       setCoords(newCoords);
10423     }
10424   //non const part
10425   setConnectivity(newc,newci,true);
10426   return ret.retn();
10427 }
10428
10429 /*!
10430  * \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.
10431  *                               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.
10432  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10433  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10434  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10435  * \param [out] addCoo - nodes to be append at the end
10436  * \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.
10437  */
10438 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10439                                          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)
10440 {
10441   static const int SPACEDIM=2;
10442   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10443   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10444   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10445   // Build BB tree of all edges in the tool mesh (second mesh)
10446   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10447   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10448   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10449   intersectEdge1.resize(nDescCell1);
10450   colinear2.resize(nDescCell2);
10451   subDiv2.resize(nDescCell2);
10452   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10453
10454   std::vector<int> candidates1(1);
10455   int offset1(m1Desc->getNumberOfNodes());
10456   int offset2(offset1+m2Desc->getNumberOfNodes());
10457   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10458     {
10459       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10460       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10461       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10462         {
10463           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10464           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10465           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10466           candidates1[0]=i;
10467           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10468           // 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
10469           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10470           std::set<INTERP_KERNEL::Node *> nodes;
10471           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10472           std::size_t szz(nodes.size());
10473           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10474           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10475           for(std::size_t iii=0;iii<szz;iii++,itt++)
10476             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10477           // end of protection
10478           // Performs egde cutting:
10479           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10480           delete pol2;
10481           delete pol1;
10482         }
10483       else
10484         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10485         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10486     }
10487 }
10488
10489 /*!
10490  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10491  * It builds the descending connectivity of the two meshes, and then using a binary tree
10492  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10493  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10494  */
10495 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10496                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10497                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10498                                                    std::vector<double>& addCoo,
10499                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10500 {
10501   // Build desc connectivity
10502   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10503   desc2=DataArrayInt::New();
10504   descIndx2=DataArrayInt::New();
10505   revDesc2=DataArrayInt::New();
10506   revDescIndx2=DataArrayInt::New();
10507   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10509   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10510   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10511   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10512   std::map<int,int> notUsedMap;
10513   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10514   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10515   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10516 }
10517
10518 /*!
10519  * This method performs the 2nd step of Partition of 2D mesh.
10520  * This method has 4 inputs :
10521  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10522  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10523  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10524  * 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'
10525  * Nodes end up lying consecutively on a cutted edge.
10526  * \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.
10527  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10528  * \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.
10529  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10530  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10531  */
10532 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10533                                            const std::vector<double>& addCoo,
10534                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10535 {
10536   int offset1=m1->getNumberOfNodes();
10537   int ncell=m2->getNumberOfCells();
10538   const int *c=m2->getNodalConnectivity()->getConstPointer();
10539   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10540   const double *coo=m2->getCoords()->getConstPointer();
10541   const double *cooBis=m1->getCoords()->getConstPointer();
10542   int offset2=offset1+m2->getNumberOfNodes();
10543   intersectEdge.resize(ncell);
10544   for(int i=0;i<ncell;i++,cI++)
10545     {
10546       const std::vector<int>& divs=subDiv[i];
10547       int nnode=cI[1]-cI[0]-1;
10548       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10549       std::map<INTERP_KERNEL::Node *, int> mapp22;
10550       for(int j=0;j<nnode;j++)
10551         {
10552           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10553           int nnid=c[(*cI)+j+1];
10554           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10555           mapp22[nn]=nnid+offset1;
10556         }
10557       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10558       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10559         ((*it).second.first)->decrRef();
10560       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10561       std::map<INTERP_KERNEL::Node *,int> mapp3;
10562       for(std::size_t j=0;j<divs.size();j++)
10563         {
10564           int id=divs[j];
10565           INTERP_KERNEL::Node *tmp=0;
10566           if(id<offset1)
10567             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10568           else if(id<offset2)
10569             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10570           else
10571             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10572           addNodes[j]=tmp;
10573           mapp3[tmp]=id;
10574         }
10575       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10576       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10577         (*it)->decrRef();
10578       e->decrRef();
10579     }
10580 }
10581
10582 /*!
10583  * 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).
10584  * 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
10585  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10586  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10587  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10588  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10589  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10590  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10591  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10592  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10593  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10594  * \param [out] cut3DSuf input/output param.
10595  */
10596 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10597                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10598                                                    const int *desc, const int *descIndx, 
10599                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10600 {
10601   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10602   int nbOf3DSurfCell=(int)cut3DSurf.size();
10603   for(int i=0;i<nbOf3DSurfCell;i++)
10604     {
10605       std::vector<int> res;
10606       int offset=descIndx[i];
10607       int nbOfSeg=descIndx[i+1]-offset;
10608       for(int j=0;j<nbOfSeg;j++)
10609         {
10610           int edgeId=desc[offset+j];
10611           int status=cut3DCurve[edgeId];
10612           if(status!=-2)
10613             {
10614               if(status>-1)
10615                 res.push_back(status);
10616               else
10617                 {
10618                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10619                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10620                 }
10621             }
10622         }
10623       switch(res.size())
10624       {
10625         case 2:
10626           {
10627             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10628             break;
10629           }
10630         case 1:
10631         case 0:
10632           {
10633             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10634             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10635             if(res.size()==2)
10636               {
10637                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10638               }
10639             else
10640               {
10641                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10642               }
10643             break;
10644           }
10645         default:
10646           {// case when plane is on a multi colinear edge of a polyhedron
10647             if((int)res.size()==2*nbOfSeg)
10648               {
10649                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10650               }
10651             else
10652               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10653           }
10654       }
10655     }
10656 }
10657
10658 /*!
10659  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10660  * 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).
10661  * 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
10662  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10663  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10664  * \param desc is the descending connectivity 3D->3DSurf
10665  * \param descIndx is the descending connectivity index 3D->3DSurf
10666  */
10667 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10668                                                   const int *desc, const int *descIndx,
10669                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10670 {
10671   checkFullyDefined();
10672   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10674   const int *nodal3D=_nodal_connec->getConstPointer();
10675   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10676   int nbOfCells=getNumberOfCells();
10677   for(int i=0;i<nbOfCells;i++)
10678     {
10679       std::map<int, std::set<int> > m;
10680       int offset=descIndx[i];
10681       int nbOfFaces=descIndx[i+1]-offset;
10682       int start=-1;
10683       int end=-1;
10684       for(int j=0;j<nbOfFaces;j++)
10685         {
10686           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10687           if(p.first!=-1 && p.second!=-1)
10688             {
10689               if(p.first!=-2)
10690                 {
10691                   start=p.first; end=p.second;
10692                   m[p.first].insert(p.second);
10693                   m[p.second].insert(p.first);
10694                 }
10695               else
10696                 {
10697                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10698                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10699                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10700                   INTERP_KERNEL::NormalizedCellType cmsId;
10701                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10702                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10703                   for(unsigned k=0;k<nbOfNodesSon;k++)
10704                     {
10705                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10706                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10707                     }
10708                 }
10709             }
10710         }
10711       if(m.empty())
10712         continue;
10713       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10714       int prev=end;
10715       while(end!=start)
10716         {
10717           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10718           const std::set<int>& s=(*it).second;
10719           std::set<int> s2; s2.insert(prev);
10720           std::set<int> s3;
10721           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10722           if(s3.size()==1)
10723             {
10724               int val=*s3.begin();
10725               conn.push_back(start);
10726               prev=start;
10727               start=val;
10728             }
10729           else
10730             start=end;
10731         }
10732       conn.push_back(end);
10733       if(conn.size()>3)
10734         {
10735           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10736           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10737           cellIds->pushBackSilent(i);
10738         }
10739     }
10740 }
10741
10742 /*!
10743  * 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
10744  * 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
10745  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10746  * 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
10747  * 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.
10748  * 
10749  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10750  */
10751 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10752 {
10753   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10754   if(sz>=4)
10755     {
10756       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10757       if(cm.getDimension()==2)
10758         {
10759           const int *node=nodalConnBg+1;
10760           int startNode=*node++;
10761           double refX=coords[2*startNode];
10762           for(;node!=nodalConnEnd;node++)
10763             {
10764               if(coords[2*(*node)]<refX)
10765                 {
10766                   startNode=*node;
10767                   refX=coords[2*startNode];
10768                 }
10769             }
10770           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10771           refX=1e300;
10772           double tmp1;
10773           double tmp2[2];
10774           double angle0=-M_PI/2;
10775           //
10776           int nextNode=-1;
10777           int prevNode=-1;
10778           double resRef;
10779           double angleNext=0.;
10780           while(nextNode!=startNode)
10781             {
10782               nextNode=-1;
10783               resRef=1e300;
10784               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10785                 {
10786                   if(*node!=tmpOut.back() && *node!=prevNode)
10787                     {
10788                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10789                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10790                       double res;
10791                       if(angleM<=angle0)
10792                         res=angle0-angleM;
10793                       else
10794                         res=angle0-angleM+2.*M_PI;
10795                       if(res<resRef)
10796                         {
10797                           nextNode=*node;
10798                           resRef=res;
10799                           angleNext=angleM;
10800                         }
10801                     }
10802                 }
10803               if(nextNode!=startNode)
10804                 {
10805                   angle0=angleNext-M_PI;
10806                   if(angle0<-M_PI)
10807                     angle0+=2*M_PI;
10808                   prevNode=tmpOut.back();
10809                   tmpOut.push_back(nextNode);
10810                 }
10811             }
10812           std::vector<int> tmp3(2*(sz-1));
10813           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10814           std::copy(nodalConnBg+1,nodalConnEnd,it);
10815           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10816             {
10817               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10818               return false;
10819             }
10820           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10821             {
10822               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10823               return false;
10824             }
10825           else
10826             {
10827               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10828               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10829               return true;
10830             }
10831         }
10832       else
10833         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10834     }
10835   else
10836     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10837 }
10838
10839 /*!
10840  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10841  * 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.
10842  * 
10843  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10844  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10845  * \param [in,out] arr array in which the remove operation will be done.
10846  * \param [in,out] arrIndx array in the remove operation will modify
10847  * \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])
10848  * \return true if \b arr and \b arrIndx have been modified, false if not.
10849  */
10850 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10851 {
10852   if(!arrIndx || !arr)
10853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10854   if(offsetForRemoval<0)
10855     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10856   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10857   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10858   int *arrIPtr=arrIndx->getPointer();
10859   *arrIPtr++=0;
10860   int previousArrI=0;
10861   const int *arrPtr=arr->getConstPointer();
10862   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10863   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10864     {
10865       if(*arrIPtr-previousArrI>offsetForRemoval)
10866         {
10867           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10868             {
10869               if(s.find(*work)==s.end())
10870                 arrOut.push_back(*work);
10871             }
10872         }
10873       previousArrI=*arrIPtr;
10874       *arrIPtr=(int)arrOut.size();
10875     }
10876   if(arr->getNumberOfTuples()==(int)arrOut.size())
10877     return false;
10878   arr->alloc((int)arrOut.size(),1);
10879   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10880   return true;
10881 }
10882
10883 /*!
10884  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10885  * (\ref numbering-indirect).
10886  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10887  * The selection of extraction is done standardly in new2old format.
10888  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10889  *
10890  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10891  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10892  * \param [in] arrIn arr origin array from which the extraction will be done.
10893  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10894  * \param [out] arrOut the resulting array
10895  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10896  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10897  */
10898 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10899                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10900 {
10901   if(!arrIn || !arrIndxIn)
10902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10903   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10904   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10905     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10906   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10907   const int *arrInPtr=arrIn->getConstPointer();
10908   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10909   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10910   if(nbOfGrps<0)
10911     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10912   int maxSizeOfArr=arrIn->getNumberOfTuples();
10913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10915   arrIo->alloc((int)(sz+1),1);
10916   const int *idsIt=idsOfSelectBg;
10917   int *work=arrIo->getPointer();
10918   *work++=0;
10919   int lgth=0;
10920   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10921     {
10922       if(*idsIt>=0 && *idsIt<nbOfGrps)
10923         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10924       else
10925         {
10926           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10927           throw INTERP_KERNEL::Exception(oss.str().c_str());
10928         }
10929       if(lgth>=work[-1])
10930         *work=lgth;
10931       else
10932         {
10933           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10934           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10935           throw INTERP_KERNEL::Exception(oss.str().c_str());
10936         }
10937     }
10938   arro->alloc(lgth,1);
10939   work=arro->getPointer();
10940   idsIt=idsOfSelectBg;
10941   for(std::size_t i=0;i<sz;i++,idsIt++)
10942     {
10943       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10944         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10945       else
10946         {
10947           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10948           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10949           throw INTERP_KERNEL::Exception(oss.str().c_str());
10950         }
10951     }
10952   arrOut=arro.retn();
10953   arrIndexOut=arrIo.retn();
10954 }
10955
10956 /*!
10957  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10958  * (\ref numbering-indirect).
10959  * 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 ).
10960  * The selection of extraction is done standardly in new2old format.
10961  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10962  *
10963  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10964  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10965  * \param [in] idsOfSelectStep
10966  * \param [in] arrIn arr origin array from which the extraction will be done.
10967  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10968  * \param [out] arrOut the resulting array
10969  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10970  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10971  */
10972 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10973                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10974 {
10975   if(!arrIn || !arrIndxIn)
10976     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10977   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10978   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10979     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10980   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10981   const int *arrInPtr=arrIn->getConstPointer();
10982   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10983   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10984   if(nbOfGrps<0)
10985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10986   int maxSizeOfArr=arrIn->getNumberOfTuples();
10987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10989   arrIo->alloc((int)(sz+1),1);
10990   int idsIt=idsOfSelectStart;
10991   int *work=arrIo->getPointer();
10992   *work++=0;
10993   int lgth=0;
10994   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10995     {
10996       if(idsIt>=0 && idsIt<nbOfGrps)
10997         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10998       else
10999         {
11000           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11001           throw INTERP_KERNEL::Exception(oss.str().c_str());
11002         }
11003       if(lgth>=work[-1])
11004         *work=lgth;
11005       else
11006         {
11007           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11008           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11009           throw INTERP_KERNEL::Exception(oss.str().c_str());
11010         }
11011     }
11012   arro->alloc(lgth,1);
11013   work=arro->getPointer();
11014   idsIt=idsOfSelectStart;
11015   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11016     {
11017       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11018         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11019       else
11020         {
11021           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11022           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11023           throw INTERP_KERNEL::Exception(oss.str().c_str());
11024         }
11025     }
11026   arrOut=arro.retn();
11027   arrIndexOut=arrIo.retn();
11028 }
11029
11030 /*!
11031  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11032  * 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
11033  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11034  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11035  *
11036  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11037  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11038  * \param [in] arrIn arr origin array from which the extraction will be done.
11039  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11040  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11041  * \param [in] srcArrIndex index array of \b srcArr
11042  * \param [out] arrOut the resulting array
11043  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11044  * 
11045  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11046  */
11047 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11048                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11049                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11050 {
11051   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11053   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11055   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11056   std::vector<bool> v(nbOfTuples,true);
11057   int offset=0;
11058   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11059   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11060   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11061     {
11062       if(*it>=0 && *it<nbOfTuples)
11063         {
11064           v[*it]=false;
11065           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11066         }
11067       else
11068         {
11069           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11070           throw INTERP_KERNEL::Exception(oss.str().c_str());
11071         }
11072     }
11073   srcArrIndexPtr=srcArrIndex->getConstPointer();
11074   arrIo->alloc(nbOfTuples+1,1);
11075   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11076   const int *arrInPtr=arrIn->getConstPointer();
11077   const int *srcArrPtr=srcArr->getConstPointer();
11078   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11079   int *arroPtr=arro->getPointer();
11080   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11081     {
11082       if(v[ii])
11083         {
11084           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11085           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11086         }
11087       else
11088         {
11089           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11090           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11091           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11092         }
11093     }
11094   arrOut=arro.retn();
11095   arrIndexOut=arrIo.retn();
11096 }
11097
11098 /*!
11099  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11100  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11101  *
11102  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11103  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11104  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11105  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11106  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11107  * \param [in] srcArrIndex index array of \b srcArr
11108  * 
11109  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11110  */
11111 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11112                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11113 {
11114   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11116   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11117   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11118   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11119   int *arrInOutPtr=arrInOut->getPointer();
11120   const int *srcArrPtr=srcArr->getConstPointer();
11121   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11122     {
11123       if(*it>=0 && *it<nbOfTuples)
11124         {
11125           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11126             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11127           else
11128             {
11129               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] !";
11130               throw INTERP_KERNEL::Exception(oss.str().c_str());
11131             }
11132         }
11133       else
11134         {
11135           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11136           throw INTERP_KERNEL::Exception(oss.str().c_str());
11137         }
11138     }
11139 }
11140
11141 /*!
11142  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11143  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11144  * 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]].
11145  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11146  * A negative value in \b arrIn means that it is ignored.
11147  * 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.
11148  * 
11149  * \param [in] arrIn arr origin array from which the extraction will be done.
11150  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11151  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11152  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11153  */
11154 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11155 {
11156   int seed=0,nbOfDepthPeelingPerformed=0;
11157   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11158 }
11159
11160 /*!
11161  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11162  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11163  * 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]].
11164  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11165  * A negative value in \b arrIn means that it is ignored.
11166  * 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.
11167  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11168  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11169  * \param [in] arrIn arr origin array from which the extraction will be done.
11170  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11171  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11172  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11173  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11174  * \sa MEDCouplingUMesh::partitionBySpreadZone
11175  */
11176 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11177 {
11178   nbOfDepthPeelingPerformed=0;
11179   if(!arrIndxIn)
11180     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11181   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11182   if(nbOfTuples<=0)
11183     {
11184       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11185       return ret;
11186     }
11187   //
11188   std::vector<bool> fetched(nbOfTuples,false);
11189   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11190 }
11191
11192 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11193 {
11194   nbOfDepthPeelingPerformed=0;
11195   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11196     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11197   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11198   std::vector<bool> fetched2(nbOfTuples,false);
11199   int i=0;
11200   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11201     {
11202       if(*seedElt>=0 && *seedElt<nbOfTuples)
11203         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11204       else
11205         { 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()); }
11206     }
11207   const int *arrInPtr=arrIn->getConstPointer();
11208   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11209   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11210   std::vector<int> idsToFetch1(seedBg,seedEnd);
11211   std::vector<int> idsToFetch2;
11212   std::vector<int> *idsToFetch=&idsToFetch1;
11213   std::vector<int> *idsToFetchOther=&idsToFetch2;
11214   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11215     {
11216       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11217         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11218           if(!fetched[*it2])
11219             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11220       std::swap(idsToFetch,idsToFetchOther);
11221       idsToFetchOther->clear();
11222       nbOfDepthPeelingPerformed++;
11223     }
11224   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11225   i=0;
11226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11227   int *retPtr=ret->getPointer();
11228   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11229     if(*it)
11230       *retPtr++=i;
11231   return ret.retn();
11232 }
11233
11234 /*!
11235  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11236  * 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
11237  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11238  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11239  *
11240  * \param [in] start begin of set of ids of the input extraction (included)
11241  * \param [in] end end of set of ids of the input extraction (excluded)
11242  * \param [in] step step of the set of ids in range mode.
11243  * \param [in] arrIn arr origin array from which the extraction will be done.
11244  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11245  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11246  * \param [in] srcArrIndex index array of \b srcArr
11247  * \param [out] arrOut the resulting array
11248  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11249  * 
11250  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11251  */
11252 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11253                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11254                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11255 {
11256   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11260   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11261   int offset=0;
11262   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11263   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11264   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11265   int it=start;
11266   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11267     {
11268       if(it>=0 && it<nbOfTuples)
11269         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11270       else
11271         {
11272           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11273           throw INTERP_KERNEL::Exception(oss.str().c_str());
11274         }
11275     }
11276   srcArrIndexPtr=srcArrIndex->getConstPointer();
11277   arrIo->alloc(nbOfTuples+1,1);
11278   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11279   const int *arrInPtr=arrIn->getConstPointer();
11280   const int *srcArrPtr=srcArr->getConstPointer();
11281   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11282   int *arroPtr=arro->getPointer();
11283   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11284     {
11285       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11286       if(pos<0)
11287         {
11288           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11289           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11290         }
11291       else
11292         {
11293           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11294           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11295         }
11296     }
11297   arrOut=arro.retn();
11298   arrIndexOut=arrIo.retn();
11299 }
11300
11301 /*!
11302  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11303  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11304  *
11305  * \param [in] start begin of set of ids of the input extraction (included)
11306  * \param [in] end end of set of ids of the input extraction (excluded)
11307  * \param [in] step step of the set of ids in range mode.
11308  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11309  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11310  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11311  * \param [in] srcArrIndex index array of \b srcArr
11312  * 
11313  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11314  */
11315 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11316                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11317 {
11318   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11320   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11321   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11322   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11323   int *arrInOutPtr=arrInOut->getPointer();
11324   const int *srcArrPtr=srcArr->getConstPointer();
11325   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11326   int it=start;
11327   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11328     {
11329       if(it>=0 && it<nbOfTuples)
11330         {
11331           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11332             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11333           else
11334             {
11335               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11336               throw INTERP_KERNEL::Exception(oss.str().c_str());
11337             }
11338         }
11339       else
11340         {
11341           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11342           throw INTERP_KERNEL::Exception(oss.str().c_str());
11343         }
11344     }
11345 }
11346
11347 /*!
11348  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11349  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11350  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11351  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11352  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11353  * 
11354  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11355  */
11356 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11357 {
11358   checkFullyDefined();
11359   int mdim=getMeshDimension();
11360   int spaceDim=getSpaceDimension();
11361   if(mdim!=spaceDim)
11362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11363   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11364   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11365   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11366   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11367   ret->setCoords(getCoords());
11368   ret->allocateCells((int)partition.size());
11369   //
11370   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11371     {
11372       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11373       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11374       switch(mdim)
11375       {
11376         case 2:
11377           cell=tmp->buildUnionOf2DMesh();
11378           break;
11379         case 3:
11380           cell=tmp->buildUnionOf3DMesh();
11381           break;
11382         default:
11383           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11384       }
11385
11386       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11387     }
11388   //
11389   ret->finishInsertingCells();
11390   return ret.retn();
11391 }
11392
11393 /*!
11394  * This method partitions \b this into contiguous zone.
11395  * This method only needs a well defined connectivity. Coordinates are not considered here.
11396  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11397  */
11398 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11399 {
11400   int nbOfCellsCur=getNumberOfCells();
11401   std::vector<DataArrayInt *> ret;
11402   if(nbOfCellsCur<=0)
11403     return ret;
11404   DataArrayInt *neigh=0,*neighI=0;
11405   computeNeighborsOfCells(neigh,neighI);
11406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11407   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11408   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11409   int seed=0;
11410   while(seed<nbOfCellsCur)
11411     {
11412       int nbOfPeelPerformed=0;
11413       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11414       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11415     }
11416   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11417     ret.push_back((*it).retn());
11418   return ret;
11419 }
11420
11421 /*!
11422  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11423  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11424  *
11425  * \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.
11426  * \return a newly allocated DataArrayInt to be managed by the caller.
11427  * \throw In case of \a code has not the right format (typically of size 3*n)
11428  */
11429 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11430 {
11431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11432   std::size_t nb=code.size()/3;
11433   if(code.size()%3!=0)
11434     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11435   ret->alloc((int)nb,2);
11436   int *retPtr=ret->getPointer();
11437   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11438     {
11439       retPtr[0]=code[3*i+2];
11440       retPtr[1]=code[3*i+2]+code[3*i+1];
11441     }
11442   return ret.retn();
11443 }
11444
11445 /*!
11446  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11447  * All cells in \a this are expected to be linear 3D cells.
11448  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11449  * It leads to an increase to number of cells.
11450  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11451  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11452  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11453  *
11454  * \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.
11455  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11456  * \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. 
11457  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11458  *          an id of old cell producing it. The caller is to delete this array using
11459  *         decrRef() as it is no more needed.
11460  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11461  *
11462  * \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
11463  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11464  * 
11465  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11466  * \throw If \a this is not fully constituted with linear 3D cells.
11467  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11468  */
11469 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11470 {
11471   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11472   checkConnectivityFullyDefined();
11473   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11475   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11476   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11478   int *retPt(ret->getPointer());
11479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11480   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11481   const int *oldc(_nodal_connec->begin());
11482   const int *oldci(_nodal_connec_index->begin());
11483   const double *coords(_coords->begin());
11484   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11485     {
11486       std::vector<int> a; std::vector<double> b;
11487       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11488       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11489       const int *aa(&a[0]);
11490       if(!b.empty())
11491         {
11492           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11493             if(*it<0)
11494               *it=(-(*(it))-1+nbNodes);
11495           addPts->insertAtTheEnd(b.begin(),b.end());
11496           nbNodes+=(int)b.size()/3;
11497         }
11498       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11499         newConn->insertAtTheEnd(aa,aa+4);
11500     }
11501   if(!addPts->empty())
11502     {
11503       addPts->rearrange(3);
11504       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11505       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11506       ret0->setCoords(addPts);
11507     }
11508   else
11509     {
11510       nbOfAdditionalPoints=0;
11511       ret0->setCoords(getCoords());
11512     }
11513   ret0->setNodalConnectivity(newConn);
11514   //
11515   ret->computeOffsets2();
11516   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11517   return ret0.retn();
11518 }
11519
11520 /*!
11521  * 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). 
11522  *
11523  * \sa MEDCouplingUMesh::split2DCells
11524  */
11525 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11526 {
11527   checkConnectivityFullyDefined();
11528   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11530   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11531   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11532   int prevPosOfCi(ciPtr[0]);
11533   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11534     {
11535       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11536       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11537       for(int j=0;j<sz;j++)
11538         {
11539           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11540           for(int k=0;k<sz2;k++)
11541             *cPtr++=subPtr[offset2+k];
11542           if(j!=sz-1)
11543             *cPtr++=oldConn[prevPosOfCi+j+2];
11544           deltaSz+=sz2;
11545         }
11546       prevPosOfCi=ciPtr[1];
11547       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11548     }
11549   if(c->end()!=cPtr)
11550     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11551   _nodal_connec->decrRef();
11552   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11553 }
11554
11555 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11556 {
11557   if(id!=-1)
11558     return id;
11559   else
11560     {
11561       int ret(nodesCnter++);
11562       double newPt[2];
11563       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11564       addCoo.insertAtTheEnd(newPt,newPt+2);
11565       return ret;
11566     }
11567 }
11568
11569 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11570 {
11571   if(id!=-1)
11572     return id;
11573   else
11574     {
11575       int ret(nodesCnter++);
11576       double newPt[2];
11577       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11578       addCoo.insertAtTheEnd(newPt,newPt+2);
11579       return ret;
11580     }
11581 }
11582
11583
11584 /// @cond INTERNAL
11585
11586 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)
11587 {
11588   int tmp[3];
11589   int trueStart(start>=0?start:nbOfEdges+start);
11590   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11591   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11592   if(linOrArc)
11593     {
11594       if(stp-start>1)
11595         {
11596           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11597           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11598           middles.push_back(tmp3+offset);
11599         }
11600       else
11601         middles.push_back(connBg[trueStart+nbOfEdges]);
11602     }
11603 }
11604
11605 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)
11606 {
11607   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11608   newConnOfCell->pushBackSilent(tmpEnd);
11609   if(linOrArc)
11610     {
11611       if(stp-start>1)
11612         {
11613           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11614           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11615           middles.push_back(tmp3+offset);
11616         }
11617       else
11618         middles.push_back(connBg[start+nbOfEdges]);
11619     }
11620 }
11621
11622 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)
11623 {
11624   // only the quadratic point to deal with:
11625   if(linOrArc)
11626     {
11627       if(stp-start>1)
11628         {
11629           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11630           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11631           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11632           middles.push_back(tmp3+offset);
11633         }
11634       else
11635         middles.push_back(connBg[start+nbOfEdges]);
11636     }
11637 }
11638
11639 /// @endcond
11640
11641 /*!
11642  * 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 ) .
11643  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11644  */
11645 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11646 {
11647   std::size_t sz(std::distance(connBg,connEnd));
11648   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11649     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11650   sz--;
11651   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11652   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11653   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11654   unsigned nbOfHit(0); // number of fusions operated
11655   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11656   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
11657   INTERP_KERNEL::NormalizedCellType typeOfSon;
11658   std::vector<int> middles;
11659   bool ret(false);
11660   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11661     {
11662       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11663       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11664       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11665       posEndElt = posBaseElt+1;
11666
11667       // Look backward first: are the final edges of the cells colinear with the first ones?
11668       // This initializes posBaseElt.
11669       if(nbOfTurn==0)
11670         {
11671           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11672             {
11673               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11674               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11675               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11676               bool isColinear=eint->areColinears();
11677               if(isColinear)
11678                 {
11679                   nbOfHit++;
11680                   posBaseElt--;
11681                   ret=true;
11682                 }
11683               delete eint;
11684               eCand->decrRef();
11685               if(!isColinear)
11686                 break;
11687             }
11688         }
11689       // Now move forward:
11690       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11691       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11692         {
11693           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11694           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11695           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11696           bool isColinear(eint->areColinears());
11697           if(isColinear)
11698             {
11699               nbOfHit++;
11700               posEndElt++;
11701               ret=true;
11702             }
11703           delete eint;
11704           eCand->decrRef();
11705           if(!isColinear)
11706               break;
11707         }
11708       //push [posBaseElt,posEndElt) in newConnOfCell using e
11709       // 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!
11710       if(nbOfTurn==0)
11711         // at the begining of the connectivity (insert type)
11712         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11713       else if((nbOfHit+nbOfTurn) != (nbs-1))
11714         // in the middle
11715         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11716       if ((nbOfHit+nbOfTurn) == (nbs-1))
11717         // at the end (only quad points to deal with)
11718         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11719       posBaseElt=posEndElt;
11720       e->decrRef();
11721     }
11722   if(!middles.empty())
11723     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11724   return ret;
11725 }
11726
11727 /*!
11728  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11729  *
11730  * \return  int - the number of new nodes created.
11731  * \sa MEDCouplingUMesh::split2DCells
11732  */
11733 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11734 {
11735   checkCoherency();
11736   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11738   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11739   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11740   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11741   const double *oldCoordsPtr(getCoords()->begin());
11742   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11743   int prevPosOfCi(ciPtr[0]);
11744   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11745     {
11746       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11747       for(int j=0;j<sz;j++)
11748         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11749       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11750       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11751         {
11752           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11753           if(sz2==0)
11754             {
11755               if(j<sz-1)
11756                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11757               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11758               continue;
11759             }
11760           std::vector<INTERP_KERNEL::Node *> ns(3);
11761           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11762           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11763           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11764           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11765           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11766             {
11767               cPtr[1]=subPtr[offset2+k];
11768               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11769             }
11770           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11771           if(j!=sz-1)
11772             { cPtr[1]=tmpEnd; }
11773           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11774         }
11775       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11776       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11777     }
11778   if(c->end()!=cPtr)
11779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11780   _nodal_connec->decrRef();
11781   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11782   addCoo->rearrange(2);
11783   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11784   setCoords(coo);
11785   return addCoo->getNumberOfTuples();
11786 }
11787
11788 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11789 {
11790   if(nodalConnec && nodalConnecIndex)
11791     {
11792       types.clear();
11793       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11794       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11795       if(nbOfElem>0)
11796         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11797           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11798     }
11799 }
11800
11801 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11802     _own_cell(true),_cell_id(-1),_nb_cell(0)
11803 {
11804   if(mesh)
11805     {
11806       mesh->incrRef();
11807       _nb_cell=mesh->getNumberOfCells();
11808     }
11809 }
11810
11811 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11812 {
11813   if(_mesh)
11814     _mesh->decrRef();
11815   if(_own_cell)
11816     delete _cell;
11817 }
11818
11819 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11820     _own_cell(false),_cell_id(bg-1),
11821     _nb_cell(end)
11822 {
11823   if(mesh)
11824     mesh->incrRef();
11825 }
11826
11827 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11828 {
11829   _cell_id++;
11830   if(_cell_id<_nb_cell)
11831     {
11832       _cell->next();
11833       return _cell;
11834     }
11835   else
11836     return 0;
11837 }
11838
11839 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11840 {
11841   if(_mesh)
11842     _mesh->incrRef();
11843 }
11844
11845 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11846 {
11847   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11848 }
11849
11850 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11851 {
11852   if(_mesh)
11853     _mesh->decrRef();
11854 }
11855
11856 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11857     _itc(itc),
11858     _bg(bg),_end(end)
11859 {
11860   if(_mesh)
11861     _mesh->incrRef();
11862 }
11863
11864 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11865 {
11866   if(_mesh)
11867     _mesh->decrRef();
11868 }
11869
11870 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11871 {
11872   return _type;
11873 }
11874
11875 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11876 {
11877   return _end-_bg;
11878 }
11879
11880 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11881 {
11882   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11883 }
11884
11885 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11886 {
11887   if(mesh)
11888     {
11889       mesh->incrRef();
11890       _nb_cell=mesh->getNumberOfCells();
11891     }
11892 }
11893
11894 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11895 {
11896   if(_mesh)
11897     _mesh->decrRef();
11898   delete _cell;
11899 }
11900
11901 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11902 {
11903   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11904   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11905   if(_cell_id<_nb_cell)
11906     {
11907       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11908       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11909       int startId=_cell_id;
11910       _cell_id+=nbOfElems;
11911       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11912     }
11913   else
11914     return 0;
11915 }
11916
11917 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11918 {
11919   if(mesh)
11920     {
11921       _conn=mesh->getNodalConnectivity()->getPointer();
11922       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11923     }
11924 }
11925
11926 void MEDCouplingUMeshCell::next()
11927 {
11928   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11929     {
11930       _conn+=_conn_lgth;
11931       _conn_indx++;
11932     }
11933   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11934 }
11935
11936 std::string MEDCouplingUMeshCell::repr() const
11937 {
11938   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11939     {
11940       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11941       oss << " : ";
11942       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11943       return oss.str();
11944     }
11945   else
11946     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11947 }
11948
11949 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11950 {
11951   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11952     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11953   else
11954     return INTERP_KERNEL::NORM_ERROR;
11955 }
11956
11957 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11958 {
11959   lgth=_conn_lgth;
11960   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11961     return _conn;
11962   else
11963     return 0;
11964 }