Salome HOME
fb05c737cba1ab4c6f96a80146a5c11ff795cd1d
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace MEDCoupling;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 /// @cond INTERNAL
57 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
58 /// @endcond
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
61 {
62   return new MEDCouplingUMesh;
63 }
64
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
66 {
67   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68   ret->setName(meshName);
69   ret->setMeshDimension(meshDim);
70   return ret;
71 }
72
73 /*!
74  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
80 {
81   return clone(true);
82 }
83
84
85 /*!
86  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88  * this mesh are shared by the new mesh.
89  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90  *          delete this mesh using decrRef() as it is no more needed. 
91  */
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
93 {
94   return new MEDCouplingUMesh(*this,recDeepCpy);
95 }
96
97 /*!
98  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
99  * The coordinates are shared between \a this and the returned instance.
100  * 
101  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102  * \sa MEDCouplingUMesh::deepCopy
103  */
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
105 {
106   checkConnectivityFullyDefined();
107   MCAuto<MEDCouplingUMesh> ret=clone(false);
108   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
109   ret->setConnectivity(c,ci);
110   return ret.retn();
111 }
112
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
114 {
115   if(!other)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
118   if(!otherC)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
122 }
123
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
125 {
126   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127   return ret;
128 }
129
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
131 {
132   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133   ret.push_back(_nodal_connec);
134   ret.push_back(_nodal_connec_index);
135   return ret;
136 }
137
138 void MEDCouplingUMesh::updateTime() const
139 {
140   MEDCouplingPointSet::updateTime();
141   if(_nodal_connec)
142     {
143       updateTimeWith(*_nodal_connec);
144     }
145   if(_nodal_connec_index)
146     {
147       updateTimeWith(*_nodal_connec_index);
148     }
149 }
150
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 {
153 }
154
155 /*!
156  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157  * then \a this mesh is most probably is writable, exchangeable and available for most
158  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159  * this method to check that all is in order with \a this mesh.
160  *  \throw If the mesh dimension is not set.
161  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
162  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163  *  \throw If the connectivity data array has more than one component.
164  *  \throw If the connectivity data array has a named component.
165  *  \throw If the connectivity index data array has more than one component.
166  *  \throw If the connectivity index data array has a named component.
167  */
168 void MEDCouplingUMesh::checkConsistencyLight() const
169 {
170   if(_mesh_dim<-1)
171     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172   if(_mesh_dim!=-1)
173     MEDCouplingPointSet::checkConsistencyLight();
174   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
175     {
176       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
177         {
178           std::ostringstream message;
179           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180           throw INTERP_KERNEL::Exception(message.str().c_str());
181         }
182     }
183   if(_nodal_connec)
184     {
185       if(_nodal_connec->getNumberOfComponents()!=1)
186         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187       if(_nodal_connec->getInfoOnComponent(0)!="")
188         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189     }
190   else
191     if(_mesh_dim!=-1)
192       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193   if(_nodal_connec_index)
194     {
195       if(_nodal_connec_index->getNumberOfComponents()!=1)
196         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197       if(_nodal_connec_index->getInfoOnComponent(0)!="")
198         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199     }
200   else
201     if(_mesh_dim!=-1)
202       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 }
204
205 /*!
206  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207  * then \a this mesh is most probably is writable, exchangeable and available for all
208  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
209  * method thoroughly checks the nodal connectivity.
210  *  \param [in] eps - a not used parameter.
211  *  \throw If the mesh dimension is not set.
212  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
213  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214  *  \throw If the connectivity data array has more than one component.
215  *  \throw If the connectivity data array has a named component.
216  *  \throw If the connectivity index data array has more than one component.
217  *  \throw If the connectivity index data array has a named component.
218  *  \throw If number of nodes defining an element does not correspond to the type of element.
219  *  \throw If the nodal connectivity includes an invalid node id.
220  */
221 void MEDCouplingUMesh::checkConsistency(double eps) const
222 {
223   checkConsistencyLight();
224   if(_mesh_dim==-1)
225     return ;
226   int meshDim=getMeshDimension();
227   int nbOfNodes=getNumberOfNodes();
228   int nbOfCells=getNumberOfCells();
229   const int *ptr=_nodal_connec->getConstPointer();
230   const int *ptrI=_nodal_connec_index->getConstPointer();
231   for(int i=0;i<nbOfCells;i++)
232     {
233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234       if((int)cm.getDimension()!=meshDim)
235         {
236           std::ostringstream oss;
237           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238           throw INTERP_KERNEL::Exception(oss.str().c_str());
239         }
240       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
241       if(!cm.isDynamic())
242         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
243           {
244             std::ostringstream oss;
245             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
246             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247             throw INTERP_KERNEL::Exception(oss.str().c_str());
248           }
249       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
251           {
252             std::ostringstream oss;
253             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
254             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255             throw INTERP_KERNEL::Exception(oss.str().c_str());
256           }
257       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
258         {
259           int nodeId=*w;
260           if(nodeId>=0)
261             {
262               if(nodeId>=nbOfNodes)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265                   throw INTERP_KERNEL::Exception(oss.str().c_str());
266                 }
267             }
268           else if(nodeId<-1)
269             {
270               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271               throw INTERP_KERNEL::Exception(oss.str().c_str());
272             }
273           else
274             {
275               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
276                 {
277                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278                   throw INTERP_KERNEL::Exception(oss.str().c_str());
279                 }
280             }
281         }
282     }
283 }
284
285 /*!
286  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
287  * elements contained in the mesh. For more info on the mesh dimension see
288  * \ref MEDCouplingUMeshPage.
289  *  \param [in] meshDim - a new mesh dimension.
290  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
291  */
292 void MEDCouplingUMesh::setMeshDimension(int meshDim)
293 {
294   if(meshDim<-1 || meshDim>3)
295     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
296   _mesh_dim=meshDim;
297   declareAsNew();
298 }
299
300 /*!
301  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
302  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
303  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
304  *
305  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
306  *
307  *  \if ENABLE_EXAMPLES
308  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
309  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
310  *  \endif
311  */
312 void MEDCouplingUMesh::allocateCells(int nbOfCells)
313 {
314   if(nbOfCells<0)
315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
316   if(_nodal_connec_index)
317     {
318       _nodal_connec_index->decrRef();
319     }
320   if(_nodal_connec)
321     {
322       _nodal_connec->decrRef();
323     }
324   _nodal_connec_index=DataArrayInt::New();
325   _nodal_connec_index->reserve(nbOfCells+1);
326   _nodal_connec_index->pushBackSilent(0);
327   _nodal_connec=DataArrayInt::New();
328   _nodal_connec->reserve(2*nbOfCells);
329   _types.clear();
330   declareAsNew();
331 }
332
333 /*!
334  * Appends a cell to the connectivity array. For deeper understanding what is
335  * happening see \ref MEDCouplingUMeshNodalConnectivity.
336  *  \param [in] type - type of cell to add.
337  *  \param [in] size - number of nodes constituting this cell.
338  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
339  * 
340  *  \if ENABLE_EXAMPLES
341  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
343  *  \endif
344  */
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
346 {
347   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348   if(_nodal_connec_index==0)
349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350   if((int)cm.getDimension()==_mesh_dim)
351     {
352       if(!cm.isDynamic())
353         if(size!=(int)cm.getNumberOfNodes())
354           {
355             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357             throw INTERP_KERNEL::Exception(oss.str().c_str());
358           }
359       int idx=_nodal_connec_index->back();
360       int val=idx+size+1;
361       _nodal_connec_index->pushBackSilent(val);
362       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
363       _types.insert(type);
364     }
365   else
366     {
367       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370       throw INTERP_KERNEL::Exception(oss.str().c_str());
371     }
372 }
373
374 /*!
375  * Compacts data arrays to release unused memory. This method is to be called after
376  * finishing cell insertion using \a this->insertNextCell().
377  * 
378  *  \if ENABLE_EXAMPLES
379  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
380  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
381  *  \endif
382  */
383 void MEDCouplingUMesh::finishInsertingCells()
384 {
385   _nodal_connec->pack();
386   _nodal_connec_index->pack();
387   _nodal_connec->declareAsNew();
388   _nodal_connec_index->declareAsNew();
389   updateTime();
390 }
391
392 /*!
393  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
394  * Useful for python users.
395  */
396 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
397 {
398   return new MEDCouplingUMeshCellIterator(this);
399 }
400
401 /*!
402  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
403  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
404  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
405  * Useful for python users.
406  */
407 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
408 {
409   if(!checkConsecutiveCellTypes())
410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
411   return new MEDCouplingUMeshCellByTypeEntry(this);
412 }
413
414 /*!
415  * Returns a set of all cell types available in \a this mesh.
416  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
417  * \warning this method does not throw any exception even if \a this is not defined.
418  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
419  */
420 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
421 {
422   return _types;
423 }
424
425 /*!
426  * This method returns the sorted list of geometric types in \a this.
427  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
428  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
429  *
430  * \throw if connectivity in \a this is not correctly defined.
431  *  
432  * \sa MEDCouplingMesh::getAllGeoTypes
433  */
434 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
435 {
436   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
437   checkConnectivityFullyDefined();
438   int nbOfCells(getNumberOfCells());
439   if(nbOfCells==0)
440     return ret;
441   if(getNodalConnectivityArrayLen()<1)
442     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
443   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
444   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
445   for(int i=1;i<nbOfCells;i++,ci++)
446     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
447       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
448   return ret;
449 }
450
451 /*!
452  * This method is a method that compares \a this and \a other.
453  * This method compares \b all attributes, even names and component names.
454  */
455 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
456 {
457   if(!other)
458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
459   std::ostringstream oss; oss.precision(15);
460   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
461   if(!otherC)
462     {
463       reason="mesh given in input is not castable in MEDCouplingUMesh !";
464       return false;
465     }
466   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
467     return false;
468   if(_mesh_dim!=otherC->_mesh_dim)
469     {
470       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
471       reason=oss.str();
472       return false;
473     }
474   if(_types!=otherC->_types)
475     {
476       oss << "umesh geometric type mismatch :\nThis geometric types are :";
477       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
478         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
479       oss << "\nOther geometric types are :";
480       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
481         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
482       reason=oss.str();
483       return false;
484     }
485   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
486     if(_nodal_connec==0 || otherC->_nodal_connec==0)
487       {
488         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
489         return false;
490       }
491   if(_nodal_connec!=otherC->_nodal_connec)
492     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
493       {
494         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
495         return false;
496       }
497   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
498     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
499       {
500         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
501         return false;
502       }
503   if(_nodal_connec_index!=otherC->_nodal_connec_index)
504     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
505       {
506         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
507         return false;
508       }
509   return true;
510 }
511
512 /*!
513  * Checks if data arrays of this mesh (node coordinates, nodal
514  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
515  * not considered.
516  *  \param [in] other - the mesh to compare with.
517  *  \param [in] prec - precision value used to compare node coordinates.
518  *  \return bool - \a true if the two meshes are same.
519  */
520 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
521 {
522   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
523   if(!otherC)
524     return false;
525   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
526     return false;
527   if(_mesh_dim!=otherC->_mesh_dim)
528     return false;
529   if(_types!=otherC->_types)
530     return false;
531   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
532     if(_nodal_connec==0 || otherC->_nodal_connec==0)
533       return false;
534   if(_nodal_connec!=otherC->_nodal_connec)
535     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
536       return false;
537   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
538     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
539       return false;
540   if(_nodal_connec_index!=otherC->_nodal_connec_index)
541     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
542       return false;
543   return true;
544 }
545
546 /*!
547  * Checks if \a this and \a other meshes are geometrically equivalent with high
548  * probability, else an exception is thrown. The meshes are considered equivalent if
549  * (1) meshes contain the same number of nodes and the same number of elements of the
550  * same types (2) three cells of the two meshes (first, last and middle) are based
551  * on coincident nodes (with a specified precision).
552  *  \param [in] other - the mesh to compare with.
553  *  \param [in] prec - the precision used to compare nodes of the two meshes.
554  *  \throw If the two meshes do not match.
555  */
556 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
557 {
558   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
559   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
560   if(!otherC)
561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
562 }
563
564 /*!
565  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
566  * cells each node belongs to.
567  * \warning For speed reasons, this method does not check if node ids in the nodal
568  *          connectivity correspond to the size of node coordinates array.
569  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
570  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
571  *        dividing cell ids in \a revNodal into groups each referring to one
572  *        node. Its every element (except the last one) is an index pointing to the
573  *         first id of a group of cells. For example cells sharing the node #1 are 
574  *        described by following range of indices: 
575  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
576  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
577  *        Number of cells sharing the *i*-th node is
578  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
579  * \throw If the coordinates array is not set.
580  * \throw If the nodal connectivity of cells is not defined.
581  * 
582  * \if ENABLE_EXAMPLES
583  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
584  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
585  * \endif
586  */
587 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
588 {
589   checkFullyDefined();
590   int nbOfNodes=getNumberOfNodes();
591   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
592   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
593   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
594   const int *conn=_nodal_connec->getConstPointer();
595   const int *connIndex=_nodal_connec_index->getConstPointer();
596   int nbOfCells=getNumberOfCells();
597   int nbOfEltsInRevNodal=0;
598   for(int eltId=0;eltId<nbOfCells;eltId++)
599     {
600       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
601       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
602       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603         if(*iter>=0)//for polyhedrons
604           {
605             nbOfEltsInRevNodal++;
606             revNodalIndxPtr[(*iter)+1]++;
607           }
608     }
609   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613   for(int eltId=0;eltId<nbOfCells;eltId++)
614     {
615       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618         if(*iter>=0)//for polyhedrons
619           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
620     }
621 }
622
623 /// @cond INTERNAL
624
625 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
626 {
627   return id;
628 }
629
630 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
631 {
632   if(!compute)
633     return id+1;
634   else
635     {
636       if(cm.getOrientationStatus(nb,conn1,conn2))
637         return id+1;
638       else
639         return -(id+1);
640     }
641 }
642
643 class MinusOneSonsGenerator
644 {
645 public:
646   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
647   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
648   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
649   static const int DELTA=1;
650 private:
651   const INTERP_KERNEL::CellModel& _cm;
652 };
653
654 class MinusOneSonsGeneratorBiQuadratic
655 {
656 public:
657   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
658   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
659   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
660   static const int DELTA=1;
661 private:
662   const INTERP_KERNEL::CellModel& _cm;
663 };
664
665 class MinusTwoSonsGenerator
666 {
667 public:
668   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
669   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
670   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
671   static const int DELTA=2;
672 private:
673   const INTERP_KERNEL::CellModel& _cm;
674 };
675
676 /// @endcond
677
678 /*!
679  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
680  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
681  * describing correspondence between cells of \a this and the result meshes are
682  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
683  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
684  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
685  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
686  * \warning For speed reasons, this method does not check if node ids in the nodal
687  *          connectivity correspond to the size of node coordinates array.
688  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
689  *          to write this mesh to the MED file, its cells must be sorted using
690  *          sortCellsInMEDFileFrmt().
691  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
692  *         each cell of \a this mesh.
693  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
694  *        dividing cell ids in \a desc into groups each referring to one
695  *        cell of \a this mesh. Its every element (except the last one) is an index
696  *        pointing to the first id of a group of cells. For example cells of the
697  *        result mesh bounding the cell #1 of \a this mesh are described by following
698  *        range of indices:
699  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
700  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
701  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
702  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
703  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
704  *         by each cell of the result mesh.
705  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
706  *        in the result mesh,
707  *        dividing cell ids in \a revDesc into groups each referring to one
708  *        cell of the result mesh the same way as \a descIndx divides \a desc.
709  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
710  *        delete this mesh using decrRef() as it is no more needed.
711  *  \throw If the coordinates array is not set.
712  *  \throw If the nodal connectivity of cells is node defined.
713  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
714  *         revDescIndx == NULL.
715  * 
716  *  \if ENABLE_EXAMPLES
717  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
718  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
719  *  \endif
720  * \sa buildDescendingConnectivity2()
721  */
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
723 {
724   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
725 }
726
727 /*!
728  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732  * \sa MEDCouplingUMesh::buildDescendingConnectivity
733  */
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
735 {
736   checkFullyDefined();
737   if(getMeshDimension()!=3)
738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
740 }
741
742 /*!
743  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744  * this->getMeshDimension(), that bound cells of \a this mesh. In
745  * addition arrays describing correspondence between cells of \a this and the result
746  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
747  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748  *  mesh. This method differs from buildDescendingConnectivity() in that apart
749  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750  * result meshes. So a positive id means that order of nodes in corresponding cells
751  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753  * i.e. cell ids are one-based.
754  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
755  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
756  * \warning For speed reasons, this method does not check if node ids in the nodal
757  *          connectivity correspond to the size of node coordinates array.
758  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759  *          to write this mesh to the MED file, its cells must be sorted using
760  *          sortCellsInMEDFileFrmt().
761  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
762  *         each cell of \a this mesh.
763  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764  *        dividing cell ids in \a desc into groups each referring to one
765  *        cell of \a this mesh. Its every element (except the last one) is an index
766  *        pointing to the first id of a group of cells. For example cells of the
767  *        result mesh bounding the cell #1 of \a this mesh are described by following
768  *        range of indices:
769  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774  *         by each cell of the result mesh.
775  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
776  *        in the result mesh,
777  *        dividing cell ids in \a revDesc into groups each referring to one
778  *        cell of the result mesh the same way as \a descIndx divides \a desc.
779  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780  *        shares the node coordinates array with \a this mesh. The caller is to
781  *        delete this mesh using decrRef() as it is no more needed.
782  *  \throw If the coordinates array is not set.
783  *  \throw If the nodal connectivity of cells is node defined.
784  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785  *         revDescIndx == NULL.
786  * 
787  *  \if ENABLE_EXAMPLES
788  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
789  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
790  *  \endif
791  * \sa buildDescendingConnectivity()
792  */
793 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
794 {
795   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
796 }
797
798 /*!
799  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
800  * For speed reasons no check of this will be done. This method calls
801  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
802  * This method lists cell by cell in \b this which are its neighbors. To compute the result
803  * only connectivities are considered.
804  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
805  * The format of return is hence \ref numbering-indirect.
806  *
807  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
808  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
809  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
810  * is equal to the last values in \b neighborsIndx.
811  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
812  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
813  */
814 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
815 {
816   MCAuto<DataArrayInt> desc=DataArrayInt::New();
817   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
818   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
819   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
820   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
821   meshDM1=0;
822   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
823 }
824
825 /*!
826  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
827  * of MEDCouplingUMesh::computeNeighborsOfCells.
828  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
829  * typically the case to extract a set a neighbours,
830  * excluding a set of meshdim-1 cells in input descending connectivity.
831  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
832  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
833  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
834  * are considered.
835  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836  *
837  * \param [in] desc descending connectivity array.
838  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
841  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
844  */
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
847 {
848   if(!desc || !descIndx || !revDesc || !revDescIndx)
849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850   const int *descPtr=desc->getConstPointer();
851   const int *descIPtr=descIndx->getConstPointer();
852   const int *revDescPtr=revDesc->getConstPointer();
853   const int *revDescIPtr=revDescIndx->getConstPointer();
854   //
855   int nbCells=descIndx->getNumberOfTuples()-1;
856   MCAuto<DataArrayInt> out0=DataArrayInt::New();
857   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858   int *out1Ptr=out1->getPointer();
859   *out1Ptr++=0;
860   out0->reserve(desc->getNumberOfTuples());
861   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862     {
863       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864         {
865           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866           s.erase(i);
867           out0->insertAtTheEnd(s.begin(),s.end());
868         }
869       *out1Ptr=out0->getNumberOfTuples();
870     }
871   neighbors=out0.retn();
872   neighborsIndx=out1.retn();
873 }
874
875 /*!
876  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877  * For speed reasons no check of this will be done. This method calls
878  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
879  * This method lists node by node in \b this which are its neighbors. To compute the result
880  * only connectivities are considered.
881  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
882  *
883  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
884  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
885  * parameter allows to select the right part in this array (\ref numbering-indirect).
886  * The number of tuples is equal to the last values in \b neighborsIndx.
887  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
888  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
889  */
890 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
891 {
892   checkFullyDefined();
893   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
894   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
895   MCAuto<MEDCouplingUMesh> mesh1D;
896   switch(mdim)
897   {
898     case 3:
899       {
900         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
901         break;
902       }
903     case 2:
904       {
905         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
906         break;
907       }
908     case 1:
909       {
910         mesh1D=const_cast<MEDCouplingUMesh *>(this);
911         mesh1D->incrRef();
912         break;
913       }
914     default:
915       {
916         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
917       }
918   }
919   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
920   mesh1D->getReverseNodalConnectivity(desc,descIndx);
921   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
922   ret0->alloc(desc->getNumberOfTuples(),1);
923   int *r0Pt(ret0->getPointer());
924   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
925   for(int i=0;i<nbNodes;i++,rni++)
926     {
927       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
928         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
929     }
930   neighbors=ret0.retn();
931   neighborsIdx=descIndx.retn();
932 }
933
934 /// @cond INTERNAL
935
936 /*!
937  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
938  * For speed reasons no check of this will be done.
939  */
940 template<class SonsGenerator>
941 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
942 {
943   if(!desc || !descIndx || !revDesc || !revDescIndx)
944     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
945   checkConnectivityFullyDefined();
946   int nbOfCells=getNumberOfCells();
947   int nbOfNodes=getNumberOfNodes();
948   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
949   int *revNodalIndxPtr=revNodalIndx->getPointer();
950   const int *conn=_nodal_connec->getConstPointer();
951   const int *connIndex=_nodal_connec_index->getConstPointer();
952   std::string name="Mesh constituent of "; name+=getName();
953   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
954   ret->setCoords(getCoords());
955   ret->allocateCells(2*nbOfCells);
956   descIndx->alloc(nbOfCells+1,1);
957   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
958   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
959   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
960     {
961       int pos=connIndex[eltId];
962       int posP1=connIndex[eltId+1];
963       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
964       SonsGenerator sg(cm);
965       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
966       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
967       for(unsigned i=0;i<nbOfSons;i++)
968         {
969           INTERP_KERNEL::NormalizedCellType cmsId;
970           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
971           for(unsigned k=0;k<nbOfNodesSon;k++)
972             if(tmp[k]>=0)
973               revNodalIndxPtr[tmp[k]+1]++;
974           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
975           revDesc2->pushBackSilent(eltId);
976         }
977       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
978     }
979   int nbOfCellsM1=ret->getNumberOfCells();
980   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
981   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
982   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
983   int *revNodalPtr=revNodal->getPointer();
984   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
985   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
986   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
987     {
988       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
989       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
990       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
991         if(*iter>=0)//for polyhedrons
992           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
993     }
994   //
995   DataArrayInt *commonCells=0,*commonCellsI=0;
996   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
997   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
998   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
999   int newNbOfCellsM1=-1;
1000   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1001                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1002   std::vector<bool> isImpacted(nbOfCellsM1,false);
1003   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1004     for(int work2=work[0];work2!=work[1];work2++)
1005       isImpacted[commonCellsPtr[work2]]=true;
1006   const int *o2nM1Ptr=o2nM1->getConstPointer();
1007   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1008   const int *n2oM1Ptr=n2oM1->getConstPointer();
1009   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1010   ret2->copyTinyInfoFrom(this);
1011   desc->alloc(descIndx->back(),1);
1012   int *descPtr=desc->getPointer();
1013   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1014   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1015     {
1016       if(!isImpacted[i])
1017         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1018       else
1019         {
1020           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1021             {
1022               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1023               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1024             }
1025           else
1026             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1027         }
1028     }
1029   revDesc->reserve(newNbOfCellsM1);
1030   revDescIndx->alloc(newNbOfCellsM1+1,1);
1031   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1032   const int *revDesc2Ptr=revDesc2->getConstPointer();
1033   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1034     {
1035       int oldCellIdM1=n2oM1Ptr[i];
1036       if(!isImpacted[oldCellIdM1])
1037         {
1038           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1039           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1040         }
1041       else
1042         {
1043           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1044             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1045           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1046           commonCellsIPtr++;
1047         }
1048     }
1049   //
1050   return ret2.retn();
1051 }
1052
1053 struct MEDCouplingAccVisit
1054 {
1055   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1056   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1057   int _new_nb_of_nodes;
1058 };
1059
1060 /// @endcond
1061
1062 /*!
1063  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1064  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1065  * array of cell ids. Pay attention that after conversion all algorithms work slower
1066  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1067  * conversion due presence of invalid ids in the array of cells to convert, as a
1068  * result \a this mesh contains some already converted elements. In this case the 2D
1069  * mesh remains valid but 3D mesh becomes \b inconsistent!
1070  *  \warning This method can significantly modify the order of geometric types in \a this,
1071  *          hence, to write this mesh to the MED file, its cells must be sorted using
1072  *          sortCellsInMEDFileFrmt().
1073  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1074  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1075  *         cellIdsToConvertBg.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If the nodal connectivity of cells is node defined.
1078  *  \throw If dimension of \a this mesh is not either 2 or 3.
1079  *
1080  *  \if ENABLE_EXAMPLES
1081  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1082  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1083  *  \endif
1084  */
1085 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1086 {
1087   checkFullyDefined();
1088   int dim=getMeshDimension();
1089   if(dim<2 || dim>3)
1090     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1091   int nbOfCells(getNumberOfCells());
1092   if(dim==2)
1093     {
1094       const int *connIndex=_nodal_connec_index->getConstPointer();
1095       int *conn=_nodal_connec->getPointer();
1096       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1097         {
1098           if(*iter>=0 && *iter<nbOfCells)
1099             {
1100               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1101               if(!cm.isQuadratic())
1102                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1103               else
1104                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1105             }
1106           else
1107             {
1108               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1109               oss << " in range [0," << nbOfCells << ") !";
1110               throw INTERP_KERNEL::Exception(oss.str().c_str());
1111             }
1112         }
1113     }
1114   else
1115     {
1116       int *connIndex(_nodal_connec_index->getPointer());
1117       const int *connOld(_nodal_connec->getConstPointer());
1118       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1119       std::vector<bool> toBeDone(nbOfCells,false);
1120       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1121         {
1122           if(*iter>=0 && *iter<nbOfCells)
1123             toBeDone[*iter]=true;
1124           else
1125             {
1126               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1127               oss << " in range [0," << nbOfCells << ") !";
1128               throw INTERP_KERNEL::Exception(oss.str().c_str());
1129             }
1130         }
1131       for(int cellId=0;cellId<nbOfCells;cellId++)
1132         {
1133           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1134           int lgthOld(posP1-pos-1);
1135           if(toBeDone[cellId])
1136             {
1137               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1138               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1139               int *tmp(new int[nbOfFaces*lgthOld+1]);
1140               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1141               for(unsigned j=0;j<nbOfFaces;j++)
1142                 {
1143                   INTERP_KERNEL::NormalizedCellType type;
1144                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1145                   work+=offset;
1146                   *work++=-1;
1147                 }
1148               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1149               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1150               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1151               delete [] tmp;
1152             }
1153           else
1154             {
1155               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1156               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1157             }
1158         }
1159       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1160     }
1161   computeTypes();
1162 }
1163
1164 /*!
1165  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1166  * polyhedrons (if \a this is a 3D mesh).
1167  *  \warning As this method is purely for user-friendliness and no optimization is
1168  *          done to avoid construction of a useless vector, this method can be costly
1169  *          in memory.
1170  *  \throw If the coordinates array is not set.
1171  *  \throw If the nodal connectivity of cells is node defined.
1172  *  \throw If dimension of \a this mesh is not either 2 or 3.
1173  */
1174 void MEDCouplingUMesh::convertAllToPoly()
1175 {
1176   int nbOfCells=getNumberOfCells();
1177   std::vector<int> cellIds(nbOfCells);
1178   for(int i=0;i<nbOfCells;i++)
1179     cellIds[i]=i;
1180   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1181 }
1182
1183 /*!
1184  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1185  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1186  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1187  * base facet of the volume and the second half of nodes describes an opposite facet
1188  * having the same number of nodes as the base one. This method converts such
1189  * connectivity to a valid polyhedral format where connectivity of each facet is
1190  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1191  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1192  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1193  * a correct orientation of the first facet of a polyhedron, else orientation of a
1194  * corrected cell is reverse.<br>
1195  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1196  * it releases the user from boring description of polyhedra connectivity in the valid
1197  * format.
1198  *  \throw If \a this->getMeshDimension() != 3.
1199  *  \throw If \a this->getSpaceDimension() != 3.
1200  *  \throw If the nodal connectivity of cells is not defined.
1201  *  \throw If the coordinates array is not set.
1202  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1203  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1204  *
1205  *  \if ENABLE_EXAMPLES
1206  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1207  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1208  *  \endif
1209  */
1210 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1211 {
1212   checkFullyDefined();
1213   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1215   int nbOfCells=getNumberOfCells();
1216   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1217   newCi->alloc(nbOfCells+1,1);
1218   int *newci=newCi->getPointer();
1219   const int *ci=_nodal_connec_index->getConstPointer();
1220   const int *c=_nodal_connec->getConstPointer();
1221   newci[0]=0;
1222   for(int i=0;i<nbOfCells;i++)
1223     {
1224       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1225       if(type==INTERP_KERNEL::NORM_POLYHED)
1226         {
1227           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1228             {
1229               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1230               throw INTERP_KERNEL::Exception(oss.str().c_str());
1231             }
1232           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1233           if(n2%2!=0)
1234             {
1235               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1236               throw INTERP_KERNEL::Exception(oss.str().c_str());
1237             }
1238           int n1=(int)(n2/2);
1239           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1240         }
1241       else
1242         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1243     }
1244   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1245   newC->alloc(newci[nbOfCells],1);
1246   int *newc=newC->getPointer();
1247   for(int i=0;i<nbOfCells;i++)
1248     {
1249       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1250       if(type==INTERP_KERNEL::NORM_POLYHED)
1251         {
1252           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1253           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1254           *newc++=-1;
1255           for(std::size_t j=0;j<n1;j++)
1256             {
1257               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1258               newc[n1+5*j]=-1;
1259               newc[n1+5*j+1]=c[ci[i]+1+j];
1260               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1261               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1262               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1263             }
1264           newc+=n1*6;
1265         }
1266       else
1267         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1268     }
1269   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1270   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1271 }
1272
1273
1274 /*!
1275  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1276  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1277  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1278  *          to write this mesh to the MED file, its cells must be sorted using
1279  *          sortCellsInMEDFileFrmt().
1280  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1281  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1282  * \return \c true if at least one cell has been converted, \c false else. In the
1283  *         last case the nodal connectivity remains unchanged.
1284  * \throw If the coordinates array is not set.
1285  * \throw If the nodal connectivity of cells is not defined.
1286  * \throw If \a this->getMeshDimension() < 0.
1287  */
1288 bool MEDCouplingUMesh::unPolyze()
1289 {
1290   checkFullyDefined();
1291   int mdim=getMeshDimension();
1292   if(mdim<0)
1293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1294   if(mdim<=1)
1295     return false;
1296   int nbOfCells=getNumberOfCells();
1297   if(nbOfCells<1)
1298     return false;
1299   int initMeshLgth=getNodalConnectivityArrayLen();
1300   int *conn=_nodal_connec->getPointer();
1301   int *index=_nodal_connec_index->getPointer();
1302   int posOfCurCell=0;
1303   int newPos=0;
1304   int lgthOfCurCell;
1305   bool ret=false;
1306   for(int i=0;i<nbOfCells;i++)
1307     {
1308       lgthOfCurCell=index[i+1]-posOfCurCell;
1309       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1310       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1311       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1312       int newLgth;
1313       if(cm.isDynamic())
1314         {
1315           switch(cm.getDimension())
1316           {
1317             case 2:
1318               {
1319                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1320                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1321                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1322                 break;
1323               }
1324             case 3:
1325               {
1326                 int nbOfFaces,lgthOfPolyhConn;
1327                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1328                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1329                 break;
1330               }
1331             case 1:
1332               {
1333                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1334                 break;
1335               }
1336           }
1337           ret=ret || (newType!=type);
1338           conn[newPos]=newType;
1339           newPos+=newLgth+1;
1340           posOfCurCell=index[i+1];
1341           index[i+1]=newPos;
1342         }
1343       else
1344         {
1345           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1346           newPos+=lgthOfCurCell;
1347           posOfCurCell+=lgthOfCurCell;
1348           index[i+1]=newPos;
1349         }
1350     }
1351   if(newPos!=initMeshLgth)
1352     _nodal_connec->reAlloc(newPos);
1353   if(ret)
1354     computeTypes();
1355   return ret;
1356 }
1357
1358 /*!
1359  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1360  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1361  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1362  *
1363  * \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 
1364  *             precision.
1365  */
1366 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1367 {
1368   checkFullyDefined();
1369   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1371   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1372   coords->recenterForMaxPrecision(eps);
1373   //
1374   int nbOfCells=getNumberOfCells();
1375   const int *conn=_nodal_connec->getConstPointer();
1376   const int *index=_nodal_connec_index->getConstPointer();
1377   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1378   connINew->alloc(nbOfCells+1,1);
1379   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1380   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1381   bool changed=false;
1382   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1383     {
1384       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1385         {
1386           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1387           changed=true;
1388         }
1389       else
1390         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1391       *connINewPtr=connNew->getNumberOfTuples();
1392     }
1393   if(changed)
1394     setConnectivity(connNew,connINew,false);
1395 }
1396
1397 /*!
1398  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1399  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1400  * the format of the returned DataArrayInt instance.
1401  * 
1402  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1403  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1404  */
1405 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1406 {
1407   checkConnectivityFullyDefined();
1408   int nbOfCells=getNumberOfCells();
1409   const int *connIndex=_nodal_connec_index->getConstPointer();
1410   const int *conn=_nodal_connec->getConstPointer();
1411   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1412   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1413   std::vector<bool> retS(maxElt,false);
1414   for(int i=0;i<nbOfCells;i++)
1415     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1416       if(conn[j]>=0)
1417         retS[conn[j]]=true;
1418   int sz=0;
1419   for(int i=0;i<maxElt;i++)
1420     if(retS[i])
1421       sz++;
1422   DataArrayInt *ret=DataArrayInt::New();
1423   ret->alloc(sz,1);
1424   int *retPtr=ret->getPointer();
1425   for(int i=0;i<maxElt;i++)
1426     if(retS[i])
1427       *retPtr++=i;
1428   return ret;
1429 }
1430
1431 /*!
1432  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1433  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1434  */
1435 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1436 {
1437   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1438   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1439   for(int i=0;i<nbOfCells;i++)
1440     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1441       if(conn[j]>=0)
1442         {
1443           if(conn[j]<nbOfNodes)
1444             nodeIdsInUse[conn[j]]=true;
1445           else
1446             {
1447               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1448               throw INTERP_KERNEL::Exception(oss.str().c_str());
1449             }
1450         }
1451 }
1452
1453 /*!
1454  * Finds nodes not used in any cell and returns an array giving a new id to every node
1455  * by excluding the unused nodes, for which the array holds -1. The result array is
1456  * a mapping in "Old to New" mode. 
1457  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1458  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1459  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1460  *          if the node is unused or a new id else. The caller is to delete this
1461  *          array using decrRef() as it is no more needed.  
1462  *  \throw If the coordinates array is not set.
1463  *  \throw If the nodal connectivity of cells is not defined.
1464  *  \throw If the nodal connectivity includes an invalid id.
1465  *
1466  *  \if ENABLE_EXAMPLES
1467  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1468  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1469  *  \endif
1470  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1471  */
1472 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1473 {
1474   nbrOfNodesInUse=-1;
1475   int nbOfNodes(getNumberOfNodes());
1476   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1477   ret->alloc(nbOfNodes,1);
1478   int *traducer=ret->getPointer();
1479   std::fill(traducer,traducer+nbOfNodes,-1);
1480   int nbOfCells=getNumberOfCells();
1481   const int *connIndex=_nodal_connec_index->getConstPointer();
1482   const int *conn=_nodal_connec->getConstPointer();
1483   for(int i=0;i<nbOfCells;i++)
1484     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1485       if(conn[j]>=0)
1486         {
1487           if(conn[j]<nbOfNodes)
1488             traducer[conn[j]]=1;
1489           else
1490             {
1491               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1492               throw INTERP_KERNEL::Exception(oss.str().c_str());
1493             }
1494         }
1495   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1496   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1497   return ret.retn();
1498 }
1499
1500 /*!
1501  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1502  * For each cell in \b this the number of nodes constituting cell is computed.
1503  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1504  * So for pohyhedrons some nodes can be counted several times in the returned result.
1505  * 
1506  * \return a newly allocated array
1507  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1508  */
1509 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1510 {
1511   checkConnectivityFullyDefined();
1512   int nbOfCells=getNumberOfCells();
1513   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1514   ret->alloc(nbOfCells,1);
1515   int *retPtr=ret->getPointer();
1516   const int *conn=getNodalConnectivity()->getConstPointer();
1517   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1518   for(int i=0;i<nbOfCells;i++,retPtr++)
1519     {
1520       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1521         *retPtr=connI[i+1]-connI[i]-1;
1522       else
1523         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1524     }
1525   return ret.retn();
1526 }
1527
1528 /*!
1529  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1530  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1531  *
1532  * \return DataArrayInt * - new object to be deallocated by the caller.
1533  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1534  */
1535 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1536 {
1537   checkConnectivityFullyDefined();
1538   int nbOfCells=getNumberOfCells();
1539   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1540   ret->alloc(nbOfCells,1);
1541   int *retPtr=ret->getPointer();
1542   const int *conn=getNodalConnectivity()->getConstPointer();
1543   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1544   for(int i=0;i<nbOfCells;i++,retPtr++)
1545     {
1546       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1547       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1548         *retPtr=(int)s.size();
1549       else
1550         {
1551           s.erase(-1);
1552           *retPtr=(int)s.size();
1553         }
1554     }
1555   return ret.retn();
1556 }
1557
1558 /*!
1559  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1560  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1561  * 
1562  * \return a newly allocated array
1563  */
1564 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1565 {
1566   checkConnectivityFullyDefined();
1567   int nbOfCells=getNumberOfCells();
1568   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1569   ret->alloc(nbOfCells,1);
1570   int *retPtr=ret->getPointer();
1571   const int *conn=getNodalConnectivity()->getConstPointer();
1572   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1573   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1574     {
1575       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1576       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1577     }
1578   return ret.retn();
1579 }
1580
1581 /*!
1582  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1583  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1584  * array mean that the corresponding old node is no more used. 
1585  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1586  *           this->getNumberOfNodes() before call of this method. The caller is to
1587  *           delete this array using decrRef() as it is no more needed. 
1588  *  \throw If the coordinates array is not set.
1589  *  \throw If the nodal connectivity of cells is not defined.
1590  *  \throw If the nodal connectivity includes an invalid id.
1591  *  \sa areAllNodesFetched
1592  *
1593  *  \if ENABLE_EXAMPLES
1594  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1595  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1596  *  \endif
1597  */
1598 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1599 {
1600   return MEDCouplingPointSet::zipCoordsTraducer();
1601 }
1602
1603 /*!
1604  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1605  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1606  */
1607 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1608 {
1609   switch(compType)
1610   {
1611     case 0:
1612       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1613     case 1:
1614       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1615     case 2:
1616       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1617     case 3:
1618       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1619     case 7:
1620       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1621   }
1622   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1623 }
1624
1625 /*!
1626  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1627  */
1628 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1631     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1632   return 0;
1633 }
1634
1635 /*!
1636  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1637  */
1638 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1639 {
1640   int sz=connI[cell1+1]-connI[cell1];
1641   if(sz==connI[cell2+1]-connI[cell2])
1642     {
1643       if(conn[connI[cell1]]==conn[connI[cell2]])
1644         {
1645           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1646           unsigned dim=cm.getDimension();
1647           if(dim!=3)
1648             {
1649               if(dim!=1)
1650                 {
1651                   int sz1=2*(sz-1);
1652                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1653                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1654                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1655                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1656                   return work!=tmp+sz1?1:0;
1657                 }
1658               else
1659                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1660             }
1661           else
1662             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1663         }
1664     }
1665   return 0;
1666 }
1667
1668 /*!
1669  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1670  */
1671 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1672 {
1673   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1674     {
1675       if(conn[connI[cell1]]==conn[connI[cell2]])
1676         {
1677           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1678           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1679           return s1==s2?1:0;
1680         }
1681     }
1682   return 0;
1683 }
1684
1685 /*!
1686  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1687  */
1688 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1689 {
1690   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1691     {
1692       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1693       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1694       return s1==s2?1:0;
1695     }
1696   return 0;
1697 }
1698
1699 /*!
1700  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1701  */
1702 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1703 {
1704   int sz=connI[cell1+1]-connI[cell1];
1705   if(sz==connI[cell2+1]-connI[cell2])
1706     {
1707       if(conn[connI[cell1]]==conn[connI[cell2]])
1708         {
1709           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1710           unsigned dim=cm.getDimension();
1711           if(dim!=3)
1712             {
1713               if(dim!=1)
1714                 {
1715                   int sz1=2*(sz-1);
1716                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1717                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1718                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1719                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1720                   if(work!=tmp+sz1)
1721                     return 1;
1722                   else
1723                     {
1724                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1725                       std::reverse_iterator<int *> it2((int *)tmp);
1726                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1727                         return 2;
1728                       else
1729                         return 0;
1730                     }
1731
1732                   return work!=tmp+sz1?1:0;
1733                 }
1734               else
1735                 {//case of SEG2 and SEG3
1736                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1737                     return 1;
1738                   if(!cm.isQuadratic())
1739                     {
1740                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1741                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1742                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1743                         return 2;
1744                       return 0;
1745                     }
1746                   else
1747                     {
1748                       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])
1749                         return 2;
1750                       return 0;
1751                     }
1752                 }
1753             }
1754           else
1755             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1756         }
1757     }
1758   return 0;
1759 }
1760
1761 /*!
1762  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1763  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1764  * and result remains unchanged.
1765  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1766  * If in 'candidates' pool -1 value is considered as an empty value.
1767  * WARNING this method returns only ONE set of result !
1768  */
1769 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1770 {
1771   if(candidates.size()<1)
1772     return false;
1773   bool ret=false;
1774   std::vector<int>::const_iterator iter=candidates.begin();
1775   int start=(*iter++);
1776   for(;iter!=candidates.end();iter++)
1777     {
1778       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1779       if(status!=0)
1780         {
1781           if(!ret)
1782             {
1783               result->pushBackSilent(start);
1784               ret=true;
1785             }
1786           if(status==1)
1787             result->pushBackSilent(*iter);
1788           else
1789             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1790         }
1791     }
1792   return ret;
1793 }
1794
1795 /*!
1796  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1797  * by \a compType.
1798  * This method keeps the coordiantes of \a this. This method is time consuming.
1799  *
1800  * \param [in] compType input specifying the technique used to compare cells each other.
1801  *   - 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.
1802  *   - 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)
1803  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1804  *   - 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
1805  * can be used for users not sensitive to orientation of cell
1806  * \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.
1807  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1808  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1809  * \return the correspondance array old to new in a newly allocated array.
1810  * 
1811  */
1812 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1813 {
1814   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1815   getReverseNodalConnectivity(revNodal,revNodalI);
1816   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1817 }
1818
1819 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1820                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1821 {
1822   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1823   int nbOfCells=nodalI->getNumberOfTuples()-1;
1824   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1825   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1826   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1827   std::vector<bool> isFetched(nbOfCells,false);
1828   if(startCellId==0)
1829     {
1830       for(int i=0;i<nbOfCells;i++)
1831         {
1832           if(!isFetched[i])
1833             {
1834               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1835               std::vector<int> v,v2;
1836               if(connOfNode!=connPtr+connIPtr[i+1])
1837                 {
1838                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1839                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1840                   connOfNode++;
1841                 }
1842               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1843                 if(*connOfNode>=0)
1844                   {
1845                     v=v2;
1846                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1847                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1848                     v2.resize(std::distance(v2.begin(),it));
1849                   }
1850               if(v2.size()>1)
1851                 {
1852                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1853                     {
1854                       int pos=commonCellsI->back();
1855                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1856                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1857                         isFetched[*it]=true;
1858                     }
1859                 }
1860             }
1861         }
1862     }
1863   else
1864     {
1865       for(int i=startCellId;i<nbOfCells;i++)
1866         {
1867           if(!isFetched[i])
1868             {
1869               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1870               std::vector<int> v,v2;
1871               if(connOfNode!=connPtr+connIPtr[i+1])
1872                 {
1873                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1874                   connOfNode++;
1875                 }
1876               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1877                 if(*connOfNode>=0)
1878                   {
1879                     v=v2;
1880                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1881                     v2.resize(std::distance(v2.begin(),it));
1882                   }
1883               if(v2.size()>1)
1884                 {
1885                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1886                     {
1887                       int pos=commonCellsI->back();
1888                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1889                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1890                         isFetched[*it]=true;
1891                     }
1892                 }
1893             }
1894         }
1895     }
1896   commonCellsArr=commonCells.retn();
1897   commonCellsIArr=commonCellsI.retn();
1898 }
1899
1900 /*!
1901  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1902  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1903  * than \a this->getNumberOfCells() in the returned array means that there is no
1904  * corresponding cell in \a this mesh.
1905  * It is expected that \a this and \a other meshes share the same node coordinates
1906  * array, if it is not so an exception is thrown. 
1907  *  \param [in] other - the mesh to compare with.
1908  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1909  *         valid values [0,1,2], see zipConnectivityTraducer().
1910  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1911  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1912  *         values. The caller is to delete this array using
1913  *         decrRef() as it is no more needed.
1914  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1915  *         mesh.
1916  *
1917  *  \if ENABLE_EXAMPLES
1918  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1919  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1920  *  \endif
1921  *  \sa checkDeepEquivalOnSameNodesWith()
1922  *  \sa checkGeoEquivalWith()
1923  */
1924 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1925 {
1926   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1927   int nbOfCells=getNumberOfCells();
1928   static const int possibleCompType[]={0,1,2};
1929   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1930     {
1931       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1932       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1933       oss << " !";
1934       throw INTERP_KERNEL::Exception(oss.str().c_str());
1935     }
1936   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1937   arr=o2n->subArray(nbOfCells);
1938   arr->setName(other->getName());
1939   int tmp;
1940   if(other->getNumberOfCells()==0)
1941     return true;
1942   return arr->getMaxValue(tmp)<nbOfCells;
1943 }
1944
1945 /*!
1946  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1947  * This method tries to determine if \b other is fully included in \b this.
1948  * The main difference is that this method is not expected to throw exception.
1949  * This method has two outputs :
1950  *
1951  * \param other other mesh
1952  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1953  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1954  */
1955 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1956 {
1957   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1958   DataArrayInt *commonCells=0,*commonCellsI=0;
1959   int thisNbCells=getNumberOfCells();
1960   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1961   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1962   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1963   int otherNbCells=other->getNumberOfCells();
1964   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
1965   arr2->alloc(otherNbCells,1);
1966   arr2->fillWithZero();
1967   int *arr2Ptr=arr2->getPointer();
1968   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1969   for(int i=0;i<nbOfCommon;i++)
1970     {
1971       int start=commonCellsPtr[commonCellsIPtr[i]];
1972       if(start<thisNbCells)
1973         {
1974           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1975             {
1976               int sig=commonCellsPtr[j]>0?1:-1;
1977               int val=std::abs(commonCellsPtr[j])-1;
1978               if(val>=thisNbCells)
1979                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1980             }
1981         }
1982     }
1983   arr2->setName(other->getName());
1984   if(arr2->presenceOfValue(0))
1985     return false;
1986   arr=arr2.retn();
1987   return true;
1988 }
1989
1990 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1991 {
1992   if(!other)
1993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1994   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1995   if(!otherC)
1996     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1997   std::vector<const MEDCouplingUMesh *> ms(2);
1998   ms[0]=this;
1999   ms[1]=otherC;
2000   return MergeUMeshesOnSameCoords(ms);
2001 }
2002
2003 /*!
2004  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2005  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2006  * cellIds is not given explicitely but by a range python like.
2007  * 
2008  * \param start
2009  * \param end
2010  * \param step
2011  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2012  * \return a newly allocated
2013  * 
2014  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2015  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2016  */
2017 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2018 {
2019   if(getMeshDimension()!=-1)
2020     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2021   else
2022     {
2023       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2024       if(newNbOfCells!=1)
2025         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2026       if(start!=0)
2027         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2028       incrRef();
2029       return const_cast<MEDCouplingUMesh *>(this);
2030     }
2031 }
2032
2033 /*!
2034  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2035  * The result mesh shares or not the node coordinates array with \a this mesh depending
2036  * on \a keepCoords parameter.
2037  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2038  *           to write this mesh to the MED file, its cells must be sorted using
2039  *           sortCellsInMEDFileFrmt().
2040  *  \param [in] begin - an array of cell ids to include to the new mesh.
2041  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2042  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2043  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2044  *         by calling zipCoords().
2045  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2046  *         to delete this mesh using decrRef() as it is no more needed. 
2047  *  \throw If the coordinates array is not set.
2048  *  \throw If the nodal connectivity of cells is not defined.
2049  *  \throw If any cell id in the array \a begin is not valid.
2050  *
2051  *  \if ENABLE_EXAMPLES
2052  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2053  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2054  *  \endif
2055  */
2056 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2057 {
2058   if(getMeshDimension()!=-1)
2059     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2060   else
2061     {
2062       if(end-begin!=1)
2063         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2064       if(begin[0]!=0)
2065         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2066       incrRef();
2067       return const_cast<MEDCouplingUMesh *>(this);
2068     }
2069 }
2070
2071 /*!
2072  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2073  *
2074  * 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.
2075  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2076  * The number of cells of \b this will remain the same with this method.
2077  *
2078  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2079  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2080  * \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 ).
2081  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2082  */
2083 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2084 {
2085   checkConnectivityFullyDefined();
2086   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2087   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2088     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2089   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2090     {
2091       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2092       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2093       throw INTERP_KERNEL::Exception(oss.str().c_str());
2094     }
2095   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2096   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2097     {
2098       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2099       throw INTERP_KERNEL::Exception(oss.str().c_str());
2100     }
2101   int nbOfCells=getNumberOfCells();
2102   bool easyAssign=true;
2103   const int *connI=_nodal_connec_index->getConstPointer();
2104   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2105   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2106     {
2107       if(*it>=0 && *it<nbOfCells)
2108         {
2109           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2110         }
2111       else
2112         {
2113           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2114           throw INTERP_KERNEL::Exception(oss.str().c_str());
2115         }
2116     }
2117   if(easyAssign)
2118     {
2119       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2120       computeTypes();
2121     }
2122   else
2123     {
2124       DataArrayInt *arrOut=0,*arrIOut=0;
2125       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2126                                                arrOut,arrIOut);
2127       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2128       setConnectivity(arrOut,arrIOut,true);
2129     }
2130 }
2131
2132 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2133 {
2134   checkConnectivityFullyDefined();
2135   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2136   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2137     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2138   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2139     {
2140       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2141       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2142       throw INTERP_KERNEL::Exception(oss.str().c_str());
2143     }
2144   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2145   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2146     {
2147       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2148       throw INTERP_KERNEL::Exception(oss.str().c_str());
2149     }
2150   int nbOfCells=getNumberOfCells();
2151   bool easyAssign=true;
2152   const int *connI=_nodal_connec_index->getConstPointer();
2153   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2154   int it=start;
2155   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2156     {
2157       if(it>=0 && it<nbOfCells)
2158         {
2159           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2160         }
2161       else
2162         {
2163           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2164           throw INTERP_KERNEL::Exception(oss.str().c_str());
2165         }
2166     }
2167   if(easyAssign)
2168     {
2169       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2170       computeTypes();
2171     }
2172   else
2173     {
2174       DataArrayInt *arrOut=0,*arrIOut=0;
2175       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2176                                                 arrOut,arrIOut);
2177       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2178       setConnectivity(arrOut,arrIOut,true);
2179     }
2180 }                      
2181
2182 /*!
2183  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2184  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2185  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2186  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2187  *
2188  * \param [in] begin input start of array of node ids.
2189  * \param [in] end input end of array of node ids.
2190  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2191  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2192  */
2193 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2194 {
2195   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2196   checkConnectivityFullyDefined();
2197   int tmp=-1;
2198   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2199   std::vector<bool> fastFinder(sz,false);
2200   for(const int *work=begin;work!=end;work++)
2201     if(*work>=0 && *work<sz)
2202       fastFinder[*work]=true;
2203   int nbOfCells=getNumberOfCells();
2204   const int *conn=getNodalConnectivity()->getConstPointer();
2205   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2206   for(int i=0;i<nbOfCells;i++)
2207     {
2208       int ref=0,nbOfHit=0;
2209       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2210         if(*work2>=0)
2211           {
2212             ref++;
2213             if(fastFinder[*work2])
2214               nbOfHit++;
2215           }
2216       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2217         cellIdsKept->pushBackSilent(i);
2218     }
2219   cellIdsKeptArr=cellIdsKept.retn();
2220 }
2221
2222 /*!
2223  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2224  * this->getMeshDimension(), that bound some cells of \a this mesh.
2225  * The cells of lower dimension to include to the result mesh are selected basing on
2226  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2227  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2228  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2229  * created mesh shares the node coordinates array with \a this mesh. 
2230  *  \param [in] begin - the array of node ids.
2231  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2232  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2233  *         array \a begin are added, else cells whose any node is in the
2234  *         array \a begin are added.
2235  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2236  *         to delete this mesh using decrRef() as it is no more needed. 
2237  *  \throw If the coordinates array is not set.
2238  *  \throw If the nodal connectivity of cells is not defined.
2239  *  \throw If any node id in \a begin is not valid.
2240  *
2241  *  \if ENABLE_EXAMPLES
2242  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2243  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2244  *  \endif
2245  */
2246 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2247 {
2248   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2249   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2250   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2251   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2252   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2253 }
2254
2255 /*!
2256  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2257  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2258  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2259  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2260  *         by calling zipCoords().
2261  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2262  *         to delete this mesh using decrRef() as it is no more needed. 
2263  *  \throw If the coordinates array is not set.
2264  *  \throw If the nodal connectivity of cells is not defined.
2265  *
2266  *  \if ENABLE_EXAMPLES
2267  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2268  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2269  *  \endif
2270  */
2271 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2272 {
2273   DataArrayInt *desc=DataArrayInt::New();
2274   DataArrayInt *descIndx=DataArrayInt::New();
2275   DataArrayInt *revDesc=DataArrayInt::New();
2276   DataArrayInt *revDescIndx=DataArrayInt::New();
2277   //
2278   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2279   revDesc->decrRef();
2280   desc->decrRef();
2281   descIndx->decrRef();
2282   int nbOfCells=meshDM1->getNumberOfCells();
2283   const int *revDescIndxC=revDescIndx->getConstPointer();
2284   std::vector<int> boundaryCells;
2285   for(int i=0;i<nbOfCells;i++)
2286     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2287       boundaryCells.push_back(i);
2288   revDescIndx->decrRef();
2289   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2290   return ret;
2291 }
2292
2293 /*!
2294  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2295  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2296  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2297  */
2298 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2299 {
2300   checkFullyDefined();
2301   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2302   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2303   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2304   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2305   //
2306   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2307   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2308   //
2309   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2310   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2311   const int *revDescPtr=revDesc->getConstPointer();
2312   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2313   int nbOfCells=getNumberOfCells();
2314   std::vector<bool> ret1(nbOfCells,false);
2315   int sz=0;
2316   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2317     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2318       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2319   //
2320   DataArrayInt *ret2=DataArrayInt::New();
2321   ret2->alloc(sz,1);
2322   int *ret2Ptr=ret2->getPointer();
2323   sz=0;
2324   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2325     if(*it)
2326       *ret2Ptr++=sz;
2327   ret2->setName("BoundaryCells");
2328   return ret2;
2329 }
2330
2331 /*!
2332  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2333  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2334  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2335  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2336  *
2337  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2338  * 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
2339  * equals a cell in \b otherDimM1OnSameCoords.
2340  *
2341  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2342  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2343  *
2344  * \param [in] otherDimM1OnSameCoords
2345  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2346  * \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
2347  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2348  */
2349 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2350 {
2351   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2353   checkConnectivityFullyDefined();
2354   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2355   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2356     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2357   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2358   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2359   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2360   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2361   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2362   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2363   DataArrayInt *idsOtherInConsti=0;
2364   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2365   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2366   if(!b)
2367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2368   std::set<int> s1;
2369   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2370     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2371   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2372   s1arr_renum1->sort();
2373   cellIdsRk0=s0arr.retn();
2374   //cellIdsRk1=s_renum1.retn();
2375   cellIdsRk1=s1arr_renum1.retn();
2376 }
2377
2378 /*!
2379  * 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
2380  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2381  * 
2382  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2383  */
2384 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2385 {
2386   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2387   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2388   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2389   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2390   //
2391   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2392   revDesc=0; desc=0; descIndx=0;
2393   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2394   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2395   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2396 }
2397
2398 /*!
2399  * Finds nodes lying on the boundary of \a this mesh.
2400  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2401  *          nodes. The caller is to delete this array using decrRef() as it is no
2402  *          more needed.
2403  *  \throw If the coordinates array is not set.
2404  *  \throw If the nodal connectivity of cells is node defined.
2405  *
2406  *  \if ENABLE_EXAMPLES
2407  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2408  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2409  *  \endif
2410  */
2411 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2412 {
2413   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2414   return skin->computeFetchedNodeIds();
2415 }
2416
2417 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2418 {
2419   incrRef();
2420   return const_cast<MEDCouplingUMesh *>(this);
2421 }
2422
2423 /*!
2424  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2425  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2426  * 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.
2427  * 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.
2428  * 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.
2429  *
2430  * \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
2431  *             parameter is altered during the call.
2432  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2433  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2434  * \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.
2435  *
2436  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2437  */
2438 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2439                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2440 {
2441   typedef MCAuto<DataArrayInt> DAInt;
2442
2443   checkFullyDefined();
2444   otherDimM1OnSameCoords.checkFullyDefined();
2445   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2447   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2448     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2449   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2450   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2451   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2452   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2453   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2454   MCAuto<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2455   DAInt s1=m0Part->computeFetchedNodeIds();
2456   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2457   DAInt s3=s2->buildSubstraction(s1);
2458   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2459   //
2460   MCAuto<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2461   int nCells2 = m0Part2->getNumberOfCells();
2462   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2463   MCAuto<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2464   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2465   DataArrayInt *tmp00=0,*tmp11=0;
2466   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2467   DAInt neighInit00(tmp00);
2468   DAInt neighIInit00(tmp11);
2469   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2470   DataArrayInt *idsTmp=0;
2471   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2472   DAInt ids(idsTmp);
2473   if(!b)
2474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2475   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2476   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2477   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2478   DataArrayInt *tmp0=0,*tmp1=0;
2479   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2480   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2481   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2482   DAInt neigh00(tmp0);
2483   DAInt neighI00(tmp1);
2484
2485   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2486   int seed = 0, nIter = 0;
2487   int nIterMax = nCells2+1; // Safety net for the loop
2488   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2489   hitCells->fillWithValue(-1);
2490   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2491   cellsToModifyConn0_torenum->alloc(0,1);
2492   while (nIter < nIterMax)
2493     {
2494       DAInt t = hitCells->findIdsEqual(-1);
2495       if (!t->getNumberOfTuples())
2496         break;
2497       // Connex zone without the crack (to compute the next seed really)
2498       int dnu;
2499       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2500       int cnt = 0;
2501       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2502         hitCells->setIJ(*ptr,0,1);
2503       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2504       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2505       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2506       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2507       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2508       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2509       DAInt intersec = nonHitCells->buildIntersection(comple);
2510       if (intersec->getNumberOfTuples())
2511         { seed = intersec->getIJ(0,0); }
2512       else
2513         { break; }
2514       nIter++;
2515     }
2516   if (nIter >= nIterMax)
2517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2518
2519   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2520   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2521   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2522   //
2523   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2524   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2525   nodeIdsToDuplicate=s3.retn();
2526 }
2527
2528 /*!
2529  * This method operates a modification of the connectivity and coords in \b this.
2530  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2531  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2532  * 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
2533  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2534  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2535  * 
2536  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2537  * 
2538  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2539  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2540  */
2541 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2542 {
2543   int nbOfNodes=getNumberOfNodes();
2544   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2545   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2546 }
2547
2548 /*!
2549  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2550  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2551  *
2552  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2553  *
2554  * \sa renumberNodesInConn
2555  */
2556 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2557 {
2558   checkConnectivityFullyDefined();
2559   int *conn(getNodalConnectivity()->getPointer());
2560   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2561   int nbOfCells(getNumberOfCells());
2562   for(int i=0;i<nbOfCells;i++)
2563     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2564       {
2565         int& node=conn[iconn];
2566         if(node>=0)//avoid polyhedron separator
2567           {
2568             node+=offset;
2569           }
2570       }
2571   _nodal_connec->declareAsNew();
2572   updateTime();
2573 }
2574
2575 /*!
2576  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2577  *  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
2578  *  of a big mesh.
2579  */
2580 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2581 {
2582   checkConnectivityFullyDefined();
2583   int *conn(getNodalConnectivity()->getPointer());
2584   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2585   int nbOfCells(getNumberOfCells());
2586   for(int i=0;i<nbOfCells;i++)
2587     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2588       {
2589         int& node=conn[iconn];
2590         if(node>=0)//avoid polyhedron separator
2591           {
2592             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2593             if(it!=newNodeNumbersO2N.end())
2594               {
2595                 node=(*it).second;
2596               }
2597             else
2598               {
2599                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2600                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2601               }
2602           }
2603       }
2604   _nodal_connec->declareAsNew();
2605   updateTime();
2606 }
2607
2608 /*!
2609  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2610  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2611  * This method is a generalization of shiftNodeNumbersInConn().
2612  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2613  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2614  *         this->getNumberOfNodes(), in "Old to New" mode. 
2615  *         See \ref numbering for more info on renumbering modes.
2616  *  \throw If the nodal connectivity of cells is not defined.
2617  *
2618  *  \if ENABLE_EXAMPLES
2619  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2620  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2621  *  \endif
2622  */
2623 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2624 {
2625   checkConnectivityFullyDefined();
2626   int *conn=getNodalConnectivity()->getPointer();
2627   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2628   int nbOfCells(getNumberOfCells());
2629   for(int i=0;i<nbOfCells;i++)
2630     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2631       {
2632         int& node=conn[iconn];
2633         if(node>=0)//avoid polyhedron separator
2634           {
2635             node=newNodeNumbersO2N[node];
2636           }
2637       }
2638   _nodal_connec->declareAsNew();
2639   updateTime();
2640 }
2641
2642 /*!
2643  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2644  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2645  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2646  * 
2647  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2648  */
2649 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2650 {
2651   checkConnectivityFullyDefined();
2652   int *conn=getNodalConnectivity()->getPointer();
2653   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2654   int nbOfCells=getNumberOfCells();
2655   for(int i=0;i<nbOfCells;i++)
2656     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2657       {
2658         int& node=conn[iconn];
2659         if(node>=0)//avoid polyhedron separator
2660           {
2661             node+=delta;
2662           }
2663       }
2664   _nodal_connec->declareAsNew();
2665   updateTime();
2666 }
2667
2668 /*!
2669  * This method operates a modification of the connectivity in \b this.
2670  * 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.
2671  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2672  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2673  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2674  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2675  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2676  * 
2677  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2678  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2679  * 
2680  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2681  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2682  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2683  */
2684 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2685 {
2686   checkConnectivityFullyDefined();
2687   std::map<int,int> m;
2688   int val=offset;
2689   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2690     m[*work]=val;
2691   int *conn=getNodalConnectivity()->getPointer();
2692   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2693   int nbOfCells=getNumberOfCells();
2694   for(int i=0;i<nbOfCells;i++)
2695     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2696       {
2697         int& node=conn[iconn];
2698         if(node>=0)//avoid polyhedron separator
2699           {
2700             std::map<int,int>::iterator it=m.find(node);
2701             if(it!=m.end())
2702               node=(*it).second;
2703           }
2704       }
2705   updateTime();
2706 }
2707
2708 /*!
2709  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2710  *
2711  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2712  * After the call of this method the number of cells remains the same as before.
2713  *
2714  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2715  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2716  * be strictly in [0;this->getNumberOfCells()).
2717  *
2718  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2719  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2720  * should be contained in[0;this->getNumberOfCells()).
2721  * 
2722  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2723  * \param check
2724  */
2725 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2726 {
2727   checkConnectivityFullyDefined();
2728   int nbCells=getNumberOfCells();
2729   const int *array=old2NewBg;
2730   if(check)
2731     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2732   //
2733   const int *conn=_nodal_connec->getConstPointer();
2734   const int *connI=_nodal_connec_index->getConstPointer();
2735   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2736   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2737   const int *n2oPtr=n2o->begin();
2738   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2739   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2740   newConn->copyStringInfoFrom(*_nodal_connec);
2741   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2742   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2743   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2744   //
2745   int *newC=newConn->getPointer();
2746   int *newCI=newConnI->getPointer();
2747   int loc=0;
2748   newCI[0]=loc;
2749   for(int i=0;i<nbCells;i++)
2750     {
2751       int pos=n2oPtr[i];
2752       int nbOfElts=connI[pos+1]-connI[pos];
2753       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2754       loc+=nbOfElts;
2755       newCI[i+1]=loc;
2756     }
2757   //
2758   setConnectivity(newConn,newConnI);
2759   if(check)
2760     free(const_cast<int *>(array));
2761 }
2762
2763 /*!
2764  * Finds cells whose bounding boxes intersect a given bounding box.
2765  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2766  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2767  *         zMax (if in 3D). 
2768  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2769  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2770  *         extent of the bounding box of cell to produce an addition to this bounding box.
2771  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2772  *         cells. The caller is to delete this array using decrRef() as it is no more
2773  *         needed. 
2774  *  \throw If the coordinates array is not set.
2775  *  \throw If the nodal connectivity of cells is not defined.
2776  *
2777  *  \if ENABLE_EXAMPLES
2778  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2779  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2780  *  \endif
2781  */
2782 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2783 {
2784   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2785   if(getMeshDimension()==-1)
2786     {
2787       elems->pushBackSilent(0);
2788       return elems.retn();
2789     }
2790   int dim=getSpaceDimension();
2791   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2792   const int* conn      = getNodalConnectivity()->getConstPointer();
2793   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2794   const double* coords = getCoords()->getConstPointer();
2795   int nbOfCells=getNumberOfCells();
2796   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2797     {
2798       for (int i=0; i<dim; i++)
2799         {
2800           elem_bb[i*2]=std::numeric_limits<double>::max();
2801           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2802         }
2803
2804       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2805         {
2806           int node= conn[inode];
2807           if(node>=0)//avoid polyhedron separator
2808             {
2809               for (int idim=0; idim<dim; idim++)
2810                 {
2811                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2812                     {
2813                       elem_bb[idim*2] = coords[node*dim+idim] ;
2814                     }
2815                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2816                     {
2817                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2818                     }
2819                 }
2820             }
2821         }
2822       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2823         elems->pushBackSilent(ielem);
2824     }
2825   return elems.retn();
2826 }
2827
2828 /*!
2829  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2830  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2831  * added in 'elems' parameter.
2832  */
2833 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2834 {
2835   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2836   if(getMeshDimension()==-1)
2837     {
2838       elems->pushBackSilent(0);
2839       return elems.retn();
2840     }
2841   int dim=getSpaceDimension();
2842   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2843   const int* conn      = getNodalConnectivity()->getConstPointer();
2844   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2845   const double* coords = getCoords()->getConstPointer();
2846   int nbOfCells=getNumberOfCells();
2847   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2848     {
2849       for (int i=0; i<dim; i++)
2850         {
2851           elem_bb[i*2]=std::numeric_limits<double>::max();
2852           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2853         }
2854
2855       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2856         {
2857           int node= conn[inode];
2858           if(node>=0)//avoid polyhedron separator
2859             {
2860               for (int idim=0; idim<dim; idim++)
2861                 {
2862                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2863                     {
2864                       elem_bb[idim*2] = coords[node*dim+idim] ;
2865                     }
2866                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2867                     {
2868                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2869                     }
2870                 }
2871             }
2872         }
2873       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2874         elems->pushBackSilent(ielem);
2875     }
2876   return elems.retn();
2877 }
2878
2879 /*!
2880  * Returns a type of a cell by its id.
2881  *  \param [in] cellId - the id of the cell of interest.
2882  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2883  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2884  */
2885 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2886 {
2887   const int *ptI=_nodal_connec_index->getConstPointer();
2888   const int *pt=_nodal_connec->getConstPointer();
2889   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2890     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2891   else
2892     {
2893       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2894       throw INTERP_KERNEL::Exception(oss.str().c_str());
2895     }
2896 }
2897
2898 /*!
2899  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2900  * This method does not throw exception if geometric type \a type is not in \a this.
2901  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2902  * The coordinates array is not considered here.
2903  *
2904  * \param [in] type the geometric type
2905  * \return cell ids in this having geometric type \a type.
2906  */
2907 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2908 {
2909
2910   MCAuto<DataArrayInt> ret=DataArrayInt::New();
2911   ret->alloc(0,1);
2912   checkConnectivityFullyDefined();
2913   int nbCells=getNumberOfCells();
2914   int mdim=getMeshDimension();
2915   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2916   if(mdim!=(int)cm.getDimension())
2917     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2918   const int *ptI=_nodal_connec_index->getConstPointer();
2919   const int *pt=_nodal_connec->getConstPointer();
2920   for(int i=0;i<nbCells;i++)
2921     {
2922       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2923         ret->pushBackSilent(i);
2924     }
2925   return ret.retn();
2926 }
2927
2928 /*!
2929  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2930  */
2931 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2932 {
2933   const int *ptI=_nodal_connec_index->getConstPointer();
2934   const int *pt=_nodal_connec->getConstPointer();
2935   int nbOfCells=getNumberOfCells();
2936   int ret=0;
2937   for(int i=0;i<nbOfCells;i++)
2938     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2939       ret++;
2940   return ret;
2941 }
2942
2943 /*!
2944  * Returns the nodal connectivity of a given cell.
2945  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2946  * all returned node ids can be used in getCoordinatesOfNode().
2947  *  \param [in] cellId - an id of the cell of interest.
2948  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2949  *         cleared before the appending.
2950  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2951  */
2952 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2953 {
2954   const int *ptI=_nodal_connec_index->getConstPointer();
2955   const int *pt=_nodal_connec->getConstPointer();
2956   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2957     if(*w>=0)
2958       conn.push_back(*w);
2959 }
2960
2961 std::string MEDCouplingUMesh::simpleRepr() const
2962 {
2963   static const char msg0[]="No coordinates specified !";
2964   std::ostringstream ret;
2965   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2966   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2967   int tmpp1,tmpp2;
2968   double tt=getTime(tmpp1,tmpp2);
2969   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2970   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2971   if(_mesh_dim>=-1)
2972     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2973   else
2974     { ret << " Mesh dimension has not been set or is invalid !"; }
2975   if(_coords!=0)
2976     {
2977       const int spaceDim=getSpaceDimension();
2978       ret << spaceDim << "\nInfo attached on space dimension : ";
2979       for(int i=0;i<spaceDim;i++)
2980         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2981       ret << "\n";
2982     }
2983   else
2984     ret << msg0 << "\n";
2985   ret << "Number of nodes : ";
2986   if(_coords!=0)
2987     ret << getNumberOfNodes() << "\n";
2988   else
2989     ret << msg0 << "\n";
2990   ret << "Number of cells : ";
2991   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2992     ret << getNumberOfCells() << "\n";
2993   else
2994     ret << "No connectivity specified !" << "\n";
2995   ret << "Cell types present : ";
2996   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2997     {
2998       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2999       ret << cm.getRepr() << " ";
3000     }
3001   ret << "\n";
3002   return ret.str();
3003 }
3004
3005 std::string MEDCouplingUMesh::advancedRepr() const
3006 {
3007   std::ostringstream ret;
3008   ret << simpleRepr();
3009   ret << "\nCoordinates array : \n___________________\n\n";
3010   if(_coords)
3011     _coords->reprWithoutNameStream(ret);
3012   else
3013     ret << "No array set !\n";
3014   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3015   reprConnectivityOfThisLL(ret);
3016   return ret.str();
3017 }
3018
3019 /*!
3020  * This method returns a C++ code that is a dump of \a this.
3021  * This method will throw if this is not fully defined.
3022  */
3023 std::string MEDCouplingUMesh::cppRepr() const
3024 {
3025   static const char coordsName[]="coords";
3026   static const char connName[]="conn";
3027   static const char connIName[]="connI";
3028   checkFullyDefined();
3029   std::ostringstream ret; ret << "// coordinates" << std::endl;
3030   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3031   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3032   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3033   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3034   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3035   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3036   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3037   return ret.str();
3038 }
3039
3040 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3041 {
3042   std::ostringstream ret;
3043   reprConnectivityOfThisLL(ret);
3044   return ret.str();
3045 }
3046
3047 /*!
3048  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3049  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3050  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3051  * some algos).
3052  * 
3053  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3054  * 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
3055  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3056  */
3057 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3058 {
3059   int mdim=getMeshDimension();
3060   if(mdim<0)
3061     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3062   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3063   MCAuto<DataArrayInt> tmp1,tmp2;
3064   bool needToCpyCT=true;
3065   if(!_nodal_connec)
3066     {
3067       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3068       needToCpyCT=false;
3069     }
3070   else
3071     {
3072       tmp1=_nodal_connec;
3073       tmp1->incrRef();
3074     }
3075   if(!_nodal_connec_index)
3076     {
3077       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3078       needToCpyCT=false;
3079     }
3080   else
3081     {
3082       tmp2=_nodal_connec_index;
3083       tmp2->incrRef();
3084     }
3085   ret->setConnectivity(tmp1,tmp2,false);
3086   if(needToCpyCT)
3087     ret->_types=_types;
3088   if(!_coords)
3089     {
3090       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3091       ret->setCoords(coords);
3092     }
3093   else
3094     ret->setCoords(_coords);
3095   return ret.retn();
3096 }
3097
3098 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3099 {
3100   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3101     {
3102       int nbOfCells=getNumberOfCells();
3103       const int *c=_nodal_connec->getConstPointer();
3104       const int *ci=_nodal_connec_index->getConstPointer();
3105       for(int i=0;i<nbOfCells;i++)
3106         {
3107           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3108           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3109           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3110           stream << "\n";
3111         }
3112     }
3113   else
3114     stream << "Connectivity not defined !\n";
3115 }
3116
3117 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3118 {
3119   const int *ptI=_nodal_connec_index->getConstPointer();
3120   const int *pt=_nodal_connec->getConstPointer();
3121   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3122     return ptI[cellId+1]-ptI[cellId]-1;
3123   else
3124     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3125 }
3126
3127 /*!
3128  * Returns types of cells of the specified part of \a this mesh.
3129  * This method avoids computing sub-mesh explicitely to get its types.
3130  *  \param [in] begin - an array of cell ids of interest.
3131  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3132  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3133  *         describing the cell types. 
3134  *  \throw If the coordinates array is not set.
3135  *  \throw If the nodal connectivity of cells is not defined.
3136  *  \sa getAllGeoTypes()
3137  */
3138 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3139 {
3140   checkFullyDefined();
3141   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3142   const int *conn=_nodal_connec->getConstPointer();
3143   const int *connIndex=_nodal_connec_index->getConstPointer();
3144   for(const int *w=begin;w!=end;w++)
3145     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3146   return ret;
3147 }
3148
3149 /*!
3150  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3151  * Optionally updates
3152  * a set of types of cells constituting \a this mesh. 
3153  * This method is for advanced users having prepared their connectivity before. For
3154  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3155  *  \param [in] conn - the nodal connectivity array. 
3156  *  \param [in] connIndex - the nodal connectivity index array.
3157  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3158  *         mesh is updated.
3159  */
3160 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3161 {
3162   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3163   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3164   if(isComputingTypes)
3165     computeTypes();
3166   declareAsNew();
3167 }
3168
3169 /*!
3170  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3171  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3172  */
3173 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3174     _nodal_connec(0),_nodal_connec_index(0),
3175     _types(other._types)
3176 {
3177   if(other._nodal_connec)
3178     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3179   if(other._nodal_connec_index)
3180     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3181 }
3182
3183 MEDCouplingUMesh::~MEDCouplingUMesh()
3184 {
3185   if(_nodal_connec)
3186     _nodal_connec->decrRef();
3187   if(_nodal_connec_index)
3188     _nodal_connec_index->decrRef();
3189 }
3190
3191 /*!
3192  * Recomputes a set of cell types of \a this mesh. For more info see
3193  * \ref MEDCouplingUMeshNodalConnectivity.
3194  */
3195 void MEDCouplingUMesh::computeTypes()
3196 {
3197   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3198 }
3199
3200 /*!
3201  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3202  */
3203 void MEDCouplingUMesh::checkFullyDefined() const
3204 {
3205   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3206     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3207 }
3208
3209 /*!
3210  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3211  */
3212 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3213 {
3214   if(!_nodal_connec_index || !_nodal_connec)
3215     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3216 }
3217
3218 /*!
3219  * Returns a number of cells constituting \a this mesh. 
3220  *  \return int - the number of cells in \a this mesh.
3221  *  \throw If the nodal connectivity of cells is not defined.
3222  */
3223 int MEDCouplingUMesh::getNumberOfCells() const
3224
3225   if(_nodal_connec_index)
3226     return _nodal_connec_index->getNumberOfTuples()-1;
3227   else
3228     if(_mesh_dim==-1)
3229       return 1;
3230     else
3231       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3232 }
3233
3234 /*!
3235  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3236  * mesh. For more info see \ref meshes.
3237  *  \return int - the dimension of \a this mesh.
3238  *  \throw If the mesh dimension is not defined using setMeshDimension().
3239  */
3240 int MEDCouplingUMesh::getMeshDimension() const
3241 {
3242   if(_mesh_dim<-1)
3243     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3244   return _mesh_dim;
3245 }
3246
3247 /*!
3248  * Returns a length of the nodal connectivity array.
3249  * This method is for test reason. Normally the integer returned is not useable by
3250  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3251  *  \return int - the length of the nodal connectivity array.
3252  */
3253 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3254 {
3255   return _nodal_connec->getNbOfElems();
3256 }
3257
3258 /*!
3259  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3260  */
3261 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3262 {
3263   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3264   tinyInfo.push_back(getMeshDimension());
3265   tinyInfo.push_back(getNumberOfCells());
3266   if(_nodal_connec)
3267     tinyInfo.push_back(getNodalConnectivityArrayLen());
3268   else
3269     tinyInfo.push_back(-1);
3270 }
3271
3272 /*!
3273  * First step of unserialization process.
3274  */
3275 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3276 {
3277   return tinyInfo[6]<=0;
3278 }
3279
3280 /*!
3281  * Second step of serialization process.
3282  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3283  * \param a1
3284  * \param a2
3285  * \param littleStrings
3286  */
3287 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3288 {
3289   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3290   if(tinyInfo[5]!=-1)
3291     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3292 }
3293
3294 /*!
3295  * Third and final step of serialization process.
3296  */
3297 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3298 {
3299   MEDCouplingPointSet::serialize(a1,a2);
3300   if(getMeshDimension()>-1)
3301     {
3302       a1=DataArrayInt::New();
3303       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3304       int *ptA1=a1->getPointer();
3305       const int *conn=getNodalConnectivity()->getConstPointer();
3306       const int *index=getNodalConnectivityIndex()->getConstPointer();
3307       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3308       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3309     }
3310   else
3311     a1=0;
3312 }
3313
3314 /*!
3315  * Second and final unserialization process.
3316  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3317  */
3318 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3319 {
3320   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3321   setMeshDimension(tinyInfo[5]);
3322   if(tinyInfo[7]!=-1)
3323     {
3324       // Connectivity
3325       const int *recvBuffer=a1->getConstPointer();
3326       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3327       myConnecIndex->alloc(tinyInfo[6]+1,1);
3328       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3329       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3330       myConnec->alloc(tinyInfo[7],1);
3331       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3332       setConnectivity(myConnec, myConnecIndex);
3333     }
3334 }
3335
3336 /*!
3337  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3338  * CellIds are given using range specified by a start an end and step.
3339  */
3340 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3341 {
3342   checkFullyDefined();
3343   int ncell=getNumberOfCells();
3344   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3345   ret->_mesh_dim=_mesh_dim;
3346   ret->setCoords(_coords);
3347   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3348   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3349   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3350   int work=start;
3351   const int *conn=_nodal_connec->getConstPointer();
3352   const int *connIndex=_nodal_connec_index->getConstPointer();
3353   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3354     {
3355       if(work>=0 && work<ncell)
3356         {
3357           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3358         }
3359       else
3360         {
3361           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3362           throw INTERP_KERNEL::Exception(oss.str().c_str());
3363         }
3364     }
3365   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3366   int *newConnPtr=newConn->getPointer();
3367   std::set<INTERP_KERNEL::NormalizedCellType> types;
3368   work=start;
3369   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3370     {
3371       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3372       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3373     }
3374   ret->setConnectivity(newConn,newConnI,false);
3375   ret->_types=types;
3376   ret->copyTinyInfoFrom(this);
3377   return ret.retn();
3378 }
3379
3380 /*!
3381  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3382  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3383  * The return newly allocated mesh will share the same coordinates as \a this.
3384  */
3385 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3386 {
3387   checkConnectivityFullyDefined();
3388   int ncell=getNumberOfCells();
3389   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3390   ret->_mesh_dim=_mesh_dim;
3391   ret->setCoords(_coords);
3392   std::size_t nbOfElemsRet=std::distance(begin,end);
3393   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3394   connIndexRet[0]=0;
3395   const int *conn=_nodal_connec->getConstPointer();
3396   const int *connIndex=_nodal_connec_index->getConstPointer();
3397   int newNbring=0;
3398   for(const int *work=begin;work!=end;work++,newNbring++)
3399     {
3400       if(*work>=0 && *work<ncell)
3401         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3402       else
3403         {
3404           free(connIndexRet);
3405           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3406           throw INTERP_KERNEL::Exception(oss.str().c_str());
3407         }
3408     }
3409   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3410   int *connRetWork=connRet;
3411   std::set<INTERP_KERNEL::NormalizedCellType> types;
3412   for(const int *work=begin;work!=end;work++)
3413     {
3414       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3415       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3416     }
3417   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3418   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3419   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3420   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3421   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3422   ret->_types=types;
3423   ret->copyTinyInfoFrom(this);
3424   return ret.retn();
3425 }
3426
3427 /*!
3428  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3429  * mesh.<br>
3430  * For 1D cells, the returned field contains lengths.<br>
3431  * For 2D cells, the returned field contains areas.<br>
3432  * For 3D cells, the returned field contains volumes.
3433  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3434  *         orientation, i.e. the volume is always positive.
3435  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3436  *         and one time . The caller is to delete this field using decrRef() as it is no
3437  *         more needed.
3438  */
3439 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3440 {
3441   std::string name="MeasureOfMesh_";
3442   name+=getName();
3443   int nbelem=getNumberOfCells();
3444   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3445   field->setName(name);
3446   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3447   array->alloc(nbelem,1);
3448   double *area_vol=array->getPointer();
3449   field->setArray(array) ; array=0;
3450   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3451   field->synchronizeTimeWithMesh();
3452   if(getMeshDimension()!=-1)
3453     {
3454       int ipt;
3455       INTERP_KERNEL::NormalizedCellType type;
3456       int dim_space=getSpaceDimension();
3457       const double *coords=getCoords()->getConstPointer();
3458       const int *connec=getNodalConnectivity()->getConstPointer();
3459       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3460       for(int iel=0;iel<nbelem;iel++)
3461         {
3462           ipt=connec_index[iel];
3463           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3464           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);
3465         }
3466       if(isAbs)
3467         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3468     }
3469   else
3470     {
3471       area_vol[0]=std::numeric_limits<double>::max();
3472     }
3473   return field.retn();
3474 }
3475
3476 /*!
3477  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3478  * mesh.<br>
3479  * For 1D cells, the returned array contains lengths.<br>
3480  * For 2D cells, the returned array contains areas.<br>
3481  * For 3D cells, the returned array contains volumes.
3482  * This method avoids building explicitly a part of \a this mesh to perform the work.
3483  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3484  *         orientation, i.e. the volume is always positive.
3485  *  \param [in] begin - an array of cell ids of interest.
3486  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3487  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3488  *          delete this array using decrRef() as it is no more needed.
3489  * 
3490  *  \if ENABLE_EXAMPLES
3491  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3492  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3493  *  \endif
3494  *  \sa getMeasureField()
3495  */
3496 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3497 {
3498   std::string name="PartMeasureOfMesh_";
3499   name+=getName();
3500   int nbelem=(int)std::distance(begin,end);
3501   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3502   array->setName(name);
3503   array->alloc(nbelem,1);
3504   double *area_vol=array->getPointer();
3505   if(getMeshDimension()!=-1)
3506     {
3507       int ipt;
3508       INTERP_KERNEL::NormalizedCellType type;
3509       int dim_space=getSpaceDimension();
3510       const double *coords=getCoords()->getConstPointer();
3511       const int *connec=getNodalConnectivity()->getConstPointer();
3512       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3513       for(const int *iel=begin;iel!=end;iel++)
3514         {
3515           ipt=connec_index[*iel];
3516           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3517           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3518         }
3519       if(isAbs)
3520         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3521     }
3522   else
3523     {
3524       area_vol[0]=std::numeric_limits<double>::max();
3525     }
3526   return array.retn();
3527 }
3528
3529 /*!
3530  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3531  * \a this one. The returned field contains the dual cell volume for each corresponding
3532  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3533  *  the dual mesh in P1 sens of \a this.<br>
3534  * For 1D cells, the returned field contains lengths.<br>
3535  * For 2D cells, the returned field contains areas.<br>
3536  * For 3D cells, the returned field contains volumes.
3537  * This method is useful to check "P1*" conservative interpolators.
3538  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3539  *         orientation, i.e. the volume is always positive.
3540  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3541  *          nodes and one time. The caller is to delete this array using decrRef() as
3542  *          it is no more needed.
3543  */
3544 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3545 {
3546   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3547   std::string name="MeasureOnNodeOfMesh_";
3548   name+=getName();
3549   int nbNodes=getNumberOfNodes();
3550   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3551   double cst=1./((double)getMeshDimension()+1.);
3552   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3553   array->alloc(nbNodes,1);
3554   double *valsToFill=array->getPointer();
3555   std::fill(valsToFill,valsToFill+nbNodes,0.);
3556   const double *values=tmp->getArray()->getConstPointer();
3557   MCAuto<DataArrayInt> da=DataArrayInt::New();
3558   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3559   getReverseNodalConnectivity(da,daInd);
3560   const int *daPtr=da->getConstPointer();
3561   const int *daIPtr=daInd->getConstPointer();
3562   for(int i=0;i<nbNodes;i++)
3563     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3564       valsToFill[i]+=cst*values[*cell];
3565   ret->setMesh(this);
3566   ret->setArray(array);
3567   return ret.retn();
3568 }
3569
3570 /*!
3571  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3572  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3573  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3574  * and are normalized.
3575  * <br> \a this can be either 
3576  * - a  2D mesh in 2D or 3D space or 
3577  * - an 1D mesh in 2D space.
3578  * 
3579  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3580  *          cells and one time. The caller is to delete this field using decrRef() as
3581  *          it is no more needed.
3582  *  \throw If the nodal connectivity of cells is not defined.
3583  *  \throw If the coordinates array is not set.
3584  *  \throw If the mesh dimension is not set.
3585  *  \throw If the mesh and space dimension is not as specified above.
3586  */
3587 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3588 {
3589   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3590     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3591   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3592   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3593   int nbOfCells=getNumberOfCells();
3594   int nbComp=getMeshDimension()+1;
3595   array->alloc(nbOfCells,nbComp);
3596   double *vals=array->getPointer();
3597   const int *connI=_nodal_connec_index->getConstPointer();
3598   const int *conn=_nodal_connec->getConstPointer();
3599   const double *coords=_coords->getConstPointer();
3600   if(getMeshDimension()==2)
3601     {
3602       if(getSpaceDimension()==3)
3603         {
3604           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3605           const double *locPtr=loc->getConstPointer();
3606           for(int i=0;i<nbOfCells;i++,vals+=3)
3607             {
3608               int offset=connI[i];
3609               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3610               double n=INTERP_KERNEL::norm<3>(vals);
3611               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3612             }
3613         }
3614       else
3615         {
3616           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3617           const double *isAbsPtr=isAbs->getArray()->begin();
3618           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3619             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3620         }
3621     }
3622   else//meshdimension==1
3623     {
3624       double tmp[2];
3625       for(int i=0;i<nbOfCells;i++)
3626         {
3627           int offset=connI[i];
3628           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3629           double n=INTERP_KERNEL::norm<2>(tmp);
3630           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3631           *vals++=-tmp[1];
3632           *vals++=tmp[0];
3633         }
3634     }
3635   ret->setArray(array);
3636   ret->setMesh(this);
3637   ret->synchronizeTimeWithSupport();
3638   return ret.retn();
3639 }
3640
3641 /*!
3642  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3643  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3644  * and are normalized.
3645  * <br> \a this can be either 
3646  * - a  2D mesh in 2D or 3D space or 
3647  * - an 1D mesh in 2D space.
3648  * 
3649  * This method avoids building explicitly a part of \a this mesh to perform the work.
3650  *  \param [in] begin - an array of cell ids of interest.
3651  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3652  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3653  *          cells and one time. The caller is to delete this field using decrRef() as
3654  *          it is no more needed.
3655  *  \throw If the nodal connectivity of cells is not defined.
3656  *  \throw If the coordinates array is not set.
3657  *  \throw If the mesh dimension is not set.
3658  *  \throw If the mesh and space dimension is not as specified above.
3659  *  \sa buildOrthogonalField()
3660  *
3661  *  \if ENABLE_EXAMPLES
3662  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3663  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3664  *  \endif
3665  */
3666 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3667 {
3668   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3669     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3670   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3671   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3672   std::size_t nbelems=std::distance(begin,end);
3673   int nbComp=getMeshDimension()+1;
3674   array->alloc((int)nbelems,nbComp);
3675   double *vals=array->getPointer();
3676   const int *connI=_nodal_connec_index->getConstPointer();
3677   const int *conn=_nodal_connec->getConstPointer();
3678   const double *coords=_coords->getConstPointer();
3679   if(getMeshDimension()==2)
3680     {
3681       if(getSpaceDimension()==3)
3682         {
3683           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3684           const double *locPtr=loc->getConstPointer();
3685           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3686             {
3687               int offset=connI[*i];
3688               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3689               double n=INTERP_KERNEL::norm<3>(vals);
3690               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3691             }
3692         }
3693       else
3694         {
3695           for(std::size_t i=0;i<nbelems;i++)
3696             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3697         }
3698     }
3699   else//meshdimension==1
3700     {
3701       double tmp[2];
3702       for(const int *i=begin;i!=end;i++)
3703         {
3704           int offset=connI[*i];
3705           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3706           double n=INTERP_KERNEL::norm<2>(tmp);
3707           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3708           *vals++=-tmp[1];
3709           *vals++=tmp[0];
3710         }
3711     }
3712   ret->setArray(array);
3713   ret->setMesh(this);
3714   ret->synchronizeTimeWithSupport();
3715   return ret.retn();
3716 }
3717
3718 /*!
3719  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3720  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3721  * and are \b not normalized.
3722  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3723  *          cells and one time. The caller is to delete this field using decrRef() as
3724  *          it is no more needed.
3725  *  \throw If the nodal connectivity of cells is not defined.
3726  *  \throw If the coordinates array is not set.
3727  *  \throw If \a this->getMeshDimension() != 1.
3728  *  \throw If \a this mesh includes cells of type other than SEG2.
3729  */
3730 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3731 {
3732   if(getMeshDimension()!=1)
3733     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3734   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3735     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3736   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3737   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3738   int nbOfCells=getNumberOfCells();
3739   int spaceDim=getSpaceDimension();
3740   array->alloc(nbOfCells,spaceDim);
3741   double *pt=array->getPointer();
3742   const double *coo=getCoords()->getConstPointer();
3743   std::vector<int> conn;
3744   conn.reserve(2);
3745   for(int i=0;i<nbOfCells;i++)
3746     {
3747       conn.resize(0);
3748       getNodeIdsOfCell(i,conn);
3749       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3750     }
3751   ret->setArray(array);
3752   ret->setMesh(this);
3753   ret->synchronizeTimeWithSupport();
3754   return ret.retn();
3755 }
3756
3757 /*!
3758  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3759  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3760  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3761  * from. If a result face is shared by two 3D cells, then the face in included twice in
3762  * the result mesh.
3763  *  \param [in] origin - 3 components of a point defining location of the plane.
3764  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3765  *         must be greater than 1e-6.
3766  *  \param [in] eps - half-thickness of the plane.
3767  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3768  *         producing correspondent 2D cells. The caller is to delete this array
3769  *         using decrRef() as it is no more needed.
3770  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3771  *         not share the node coordinates array with \a this mesh. The caller is to
3772  *         delete this mesh using decrRef() as it is no more needed.  
3773  *  \throw If the coordinates array is not set.
3774  *  \throw If the nodal connectivity of cells is not defined.
3775  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3776  *  \throw If magnitude of \a vec is less than 1e-6.
3777  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3778  *  \throw If \a this includes quadratic cells.
3779  */
3780 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3781 {
3782   checkFullyDefined();
3783   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3785   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3786   if(candidates->empty())
3787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3788   std::vector<int> nodes;
3789   DataArrayInt *cellIds1D=0;
3790   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3791   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3792   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3793   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3794   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3795   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3796   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3797   revDesc2=0; revDescIndx2=0;
3798   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3799   revDesc1=0; revDescIndx1=0;
3800   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3801   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3802   //
3803   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3804   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3805     cut3DCurve[*it]=-1;
3806   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3807   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3808   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3809                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3810                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3811   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3812   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3813   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3814   if(cellIds2->empty())
3815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3816   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3817   ret->setCoords(mDesc1->getCoords());
3818   ret->setConnectivity(conn,connI,true);
3819   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3820   return ret.retn();
3821 }
3822
3823 /*!
3824  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3825 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
3826 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3827 the result mesh.
3828  *  \param [in] origin - 3 components of a point defining location of the plane.
3829  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3830  *         must be greater than 1e-6.
3831  *  \param [in] eps - half-thickness of the plane.
3832  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3833  *         producing correspondent segments. The caller is to delete this array
3834  *         using decrRef() as it is no more needed.
3835  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3836  *         mesh in 3D space. This mesh does not share the node coordinates array with
3837  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3838  *         no more needed. 
3839  *  \throw If the coordinates array is not set.
3840  *  \throw If the nodal connectivity of cells is not defined.
3841  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3842  *  \throw If magnitude of \a vec is less than 1e-6.
3843  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3844  *  \throw If \a this includes quadratic cells.
3845  */
3846 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3847 {
3848   checkFullyDefined();
3849   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3851   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3852   if(candidates->empty())
3853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3854   std::vector<int> nodes;
3855   DataArrayInt *cellIds1D=0;
3856   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3857   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3858   MCAuto<DataArrayInt> desc1=DataArrayInt::New();
3859   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New();
3860   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New();
3861   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New();
3862   MCAuto<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3863   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3864   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3865   //
3866   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3867   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3868     cut3DCurve[*it]=-1;
3869   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3870   int ncellsSub=subMesh->getNumberOfCells();
3871   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3872   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3873                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3874                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3875   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3876   conn->alloc(0,1);
3877   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3878   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3879   for(int i=0;i<ncellsSub;i++)
3880     {
3881       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3882         {
3883           if(cut3DSurf[i].first!=-2)
3884             {
3885               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3886               connI->pushBackSilent(conn->getNumberOfTuples());
3887               cellIds2->pushBackSilent(i);
3888             }
3889           else
3890             {
3891               int cellId3DSurf=cut3DSurf[i].second;
3892               int offset=nodalI[cellId3DSurf]+1;
3893               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3894               for(int j=0;j<nbOfEdges;j++)
3895                 {
3896                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3897                   connI->pushBackSilent(conn->getNumberOfTuples());
3898                   cellIds2->pushBackSilent(cellId3DSurf);
3899                 }
3900             }
3901         }
3902     }
3903   if(cellIds2->empty())
3904     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3905   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3906   ret->setCoords(mDesc1->getCoords());
3907   ret->setConnectivity(conn,connI,true);
3908   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3909   return ret.retn();
3910 }
3911
3912 /*!
3913  * Finds cells whose bounding boxes intersect a given plane.
3914  *  \param [in] origin - 3 components of a point defining location of the plane.
3915  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3916  *         must be greater than 1e-6.
3917  *  \param [in] eps - half-thickness of the plane.
3918  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3919  *         cells. The caller is to delete this array using decrRef() as it is no more
3920  *         needed.
3921  *  \throw If the coordinates array is not set.
3922  *  \throw If the nodal connectivity of cells is not defined.
3923  *  \throw If \a this->getSpaceDimension() != 3.
3924  *  \throw If magnitude of \a vec is less than 1e-6.
3925  *  \sa buildSlice3D()
3926  */
3927 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3928 {
3929   checkFullyDefined();
3930   if(getSpaceDimension()!=3)
3931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3932   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3933   if(normm<1e-6)
3934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3935   double vec2[3];
3936   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3937   double angle=acos(vec[2]/normm);
3938   MCAuto<DataArrayInt> cellIds;
3939   double bbox[6];
3940   if(angle>eps)
3941     {
3942       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3943       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3944       if(normm2/normm>1e-6)
3945         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3946       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3947       mw->setCoords(coo);
3948       mw->getBoundingBox(bbox);
3949       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3950       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3951     }
3952   else
3953     {
3954       getBoundingBox(bbox);
3955       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3956       cellIds=getCellsInBoundingBox(bbox,eps);
3957     }
3958   return cellIds.retn();
3959 }
3960
3961 /*!
3962  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3963  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3964  * No consideration of coordinate is done by this method.
3965  * 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)
3966  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
3967  */
3968 bool MEDCouplingUMesh::isContiguous1D() const
3969 {
3970   if(getMeshDimension()!=1)
3971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3972   int nbCells=getNumberOfCells();
3973   if(nbCells<1)
3974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3975   const int *connI=_nodal_connec_index->getConstPointer();
3976   const int *conn=_nodal_connec->getConstPointer();
3977   int ref=conn[connI[0]+2];
3978   for(int i=1;i<nbCells;i++)
3979     {
3980       if(conn[connI[i]+1]!=ref)
3981         return false;
3982       ref=conn[connI[i]+2];
3983     }
3984   return true;
3985 }
3986
3987 /*!
3988  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3989  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3990  * \param pt reference point of the line
3991  * \param v normalized director vector of the line
3992  * \param eps max precision before throwing an exception
3993  * \param res output of size this->getNumberOfCells
3994  */
3995 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3996 {
3997   if(getMeshDimension()!=1)
3998     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3999   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4000     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4001   if(getSpaceDimension()!=3)
4002     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4003   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4004   const double *fPtr=f->getArray()->getConstPointer();
4005   double tmp[3];
4006   for(int i=0;i<getNumberOfCells();i++)
4007     {
4008       const double *tmp1=fPtr+3*i;
4009       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4010       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4011       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4012       double n1=INTERP_KERNEL::norm<3>(tmp);
4013       n1/=INTERP_KERNEL::norm<3>(tmp1);
4014       if(n1>eps)
4015         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4016     }
4017   const double *coo=getCoords()->getConstPointer();
4018   for(int i=0;i<getNumberOfNodes();i++)
4019     {
4020       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4021       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4022       res[i]=std::accumulate(tmp,tmp+3,0.);
4023     }
4024 }
4025
4026 /*!
4027  * 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. 
4028  * \a this is expected to be a mesh so that its space dimension is equal to its
4029  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4030  * 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).
4031  *
4032  * 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
4033  * 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).
4034  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4035  *
4036  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4037  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4038  *
4039  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4040  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4041  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4042  * \return the positive value of the distance.
4043  * \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
4044  * dimension - 1.
4045  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4046  */
4047 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4048 {
4049   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4050   if(meshDim!=spaceDim-1)
4051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4052   if(meshDim!=2 && meshDim!=1)
4053     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4054   checkFullyDefined();
4055   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4056     { 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()); }
4057   DataArrayInt *ret1=0;
4058   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4059   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4060   MCAuto<DataArrayInt> ret1Safe(ret1);
4061   cellId=*ret1Safe->begin();
4062   return *ret0->begin();
4063 }
4064
4065 /*!
4066  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4067  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4068  * 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
4069  * 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).
4070  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4071  * 
4072  * \a this is expected to be a mesh so that its space dimension is equal to its
4073  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4074  * 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).
4075  *
4076  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4077  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4078  *
4079  * \param [in] pts the list of points in which each tuple represents a point
4080  * \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.
4081  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4082  * \throw if number of components of \a pts is not equal to the space dimension.
4083  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4084  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4085  */
4086 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4087 {
4088   if(!pts)
4089     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4090   pts->checkAllocated();
4091   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4092   if(meshDim!=spaceDim-1)
4093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4094   if(meshDim!=2 && meshDim!=1)
4095     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4096   if(pts->getNumberOfComponents()!=spaceDim)
4097     {
4098       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4099       throw INTERP_KERNEL::Exception(oss.str().c_str());
4100     }
4101   checkFullyDefined();
4102   int nbCells=getNumberOfCells();
4103   if(nbCells==0)
4104     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4105   int nbOfPts=pts->getNumberOfTuples();
4106   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4107   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4108   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4109   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4110   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4111   const double *bbox(bboxArr->begin());
4112   switch(spaceDim)
4113   {
4114     case 3:
4115       {
4116         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4117         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4118           {
4119             double x=std::numeric_limits<double>::max();
4120             std::vector<int> elems;
4121             myTree.getMinDistanceOfMax(ptsPtr,x);
4122             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4123             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4124           }
4125         break;
4126       }
4127     case 2:
4128       {
4129         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4130         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4131           {
4132             double x=std::numeric_limits<double>::max();
4133             std::vector<int> elems;
4134             myTree.getMinDistanceOfMax(ptsPtr,x);
4135             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4136             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4137           }
4138         break;
4139       }
4140     default:
4141       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4142   }
4143   cellIds=ret1.retn();
4144   return ret0.retn();
4145 }
4146
4147 /// @cond INTERNAL
4148
4149 /*!
4150  * \param [in] pt the start pointer (included) of the coordinates of the point
4151  * \param [in] cellIdsBg the start pointer (included) of cellIds
4152  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4153  * \param [in] nc nodal connectivity
4154  * \param [in] ncI nodal connectivity index
4155  * \param [in,out] ret0 the min distance between \a this and the external input point
4156  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4157  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4158  */
4159 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)
4160 {
4161   cellId=-1;
4162   ret0=std::numeric_limits<double>::max();
4163   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4164     {
4165       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4166       {
4167         case INTERP_KERNEL::NORM_TRI3:
4168           {
4169             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4170             if(tmp<ret0)
4171               { ret0=tmp; cellId=*zeCell; }
4172             break;
4173           }
4174         case INTERP_KERNEL::NORM_QUAD4:
4175         case INTERP_KERNEL::NORM_POLYGON:
4176           {
4177             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4178             if(tmp<ret0)
4179               { ret0=tmp; cellId=*zeCell; }
4180             break;
4181           }
4182         default:
4183           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4184       }
4185     }
4186 }
4187
4188 /*!
4189  * \param [in] pt the start pointer (included) of the coordinates of the point
4190  * \param [in] cellIdsBg the start pointer (included) of cellIds
4191  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4192  * \param [in] nc nodal connectivity
4193  * \param [in] ncI nodal connectivity index
4194  * \param [in,out] ret0 the min distance between \a this and the external input point
4195  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4196  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4197  */
4198 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)
4199 {
4200   cellId=-1;
4201   ret0=std::numeric_limits<double>::max();
4202   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4203     {
4204       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4205       {
4206         case INTERP_KERNEL::NORM_SEG2:
4207           {
4208             std::size_t uselessEntry=0;
4209             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4210             tmp=sqrt(tmp);
4211             if(tmp<ret0)
4212               { ret0=tmp; cellId=*zeCell; }
4213             break;
4214           }
4215         default:
4216           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4217       }
4218     }
4219 }
4220 /// @endcond
4221
4222 /*!
4223  * Finds cells in contact with a ball (i.e. a point with precision). 
4224  * 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.
4225  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4226  *
4227  * \warning This method is suitable if the caller intends to evaluate only one
4228  *          point, for more points getCellsContainingPoints() is recommended as it is
4229  *          faster. 
4230  *  \param [in] pos - array of coordinates of the ball central point.
4231  *  \param [in] eps - ball radius.
4232  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4233  *         if there are no such cells.
4234  *  \throw If the coordinates array is not set.
4235  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4236  */
4237 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4238 {
4239   std::vector<int> elts;
4240   getCellsContainingPoint(pos,eps,elts);
4241   if(elts.empty())
4242     return -1;
4243   return elts.front();
4244 }
4245
4246 /*!
4247  * Finds cells in contact with a ball (i.e. a point with precision).
4248  * 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.
4249  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4250  * \warning This method is suitable if the caller intends to evaluate only one
4251  *          point, for more points getCellsContainingPoints() is recommended as it is
4252  *          faster. 
4253  *  \param [in] pos - array of coordinates of the ball central point.
4254  *  \param [in] eps - ball radius.
4255  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4256  *         before inserting ids.
4257  *  \throw If the coordinates array is not set.
4258  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4259  *
4260  *  \if ENABLE_EXAMPLES
4261  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4262  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4263  *  \endif
4264  */
4265 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4266 {
4267   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4268   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4269   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4270 }
4271
4272 /// @cond INTERNAL
4273
4274 namespace MEDCoupling
4275 {
4276   template<const int SPACEDIMM>
4277   class DummyClsMCUG
4278   {
4279   public:
4280     static const int MY_SPACEDIM=SPACEDIMM;
4281     static const int MY_MESHDIM=8;
4282     typedef int MyConnType;
4283     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4284     // begin
4285     // useless, but for windows compilation ...
4286     const double* getCoordinatesPtr() const { return 0; }
4287     const int* getConnectivityPtr() const { return 0; }
4288     const int* getConnectivityIndexPtr() const { return 0; }
4289     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4290     // end
4291   };
4292
4293   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4294   {
4295     INTERP_KERNEL::Edge *ret(0);
4296     MCAuto<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4297     m[n0]=bg[0]; m[n1]=bg[1];
4298     switch(typ)
4299     {
4300       case INTERP_KERNEL::NORM_SEG2:
4301         {
4302           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4303           break;
4304         }
4305       case INTERP_KERNEL::NORM_SEG3:
4306         {
4307           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4308           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4309           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4310           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4311           bool colinearity(inters.areColinears());
4312           delete e1; delete e2;
4313           if(colinearity)
4314             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4315           else
4316             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4317           break;
4318         }
4319       default:
4320         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4321     }
4322     return ret;
4323   }
4324
4325   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4326   {
4327     INTERP_KERNEL::Edge *ret=0;
4328     switch(typ)
4329     {
4330       case INTERP_KERNEL::NORM_SEG2:
4331         {
4332           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4333           break;
4334         }
4335       case INTERP_KERNEL::NORM_SEG3:
4336         {
4337           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4338           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4339           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4340           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4341           bool colinearity=inters.areColinears();
4342           delete e1; delete e2;
4343           if(colinearity)
4344             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4345           else
4346             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4347           mapp2[bg[2]].second=false;
4348           break;
4349         }
4350       default:
4351         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4352     }
4353     return ret;
4354   }
4355
4356   /*!
4357    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4358    * the global mesh 'mDesc'.
4359    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4360    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4361    */
4362   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4363                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4364   {
4365     mapp.clear();
4366     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.
4367     const double *coo=mDesc->getCoords()->getConstPointer();
4368     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4369     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4370     std::set<int> s;
4371     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4372       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4373     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4374       {
4375         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4376         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4377       }
4378     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4379     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4380       {
4381         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4382         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4383       }
4384     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4385       {
4386         if((*it2).second.second)
4387           mapp[(*it2).second.first]=(*it2).first;
4388         ((*it2).second.first)->decrRef();
4389       }
4390     return ret;
4391   }
4392
4393   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4394   {
4395     if(nodeId>=offset2)
4396       {
4397         int locId=nodeId-offset2;
4398         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4399       }
4400     if(nodeId>=offset1)
4401       {
4402         int locId=nodeId-offset1;
4403         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4404       }
4405     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4406   }
4407
4408   /**
4409    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4410    */
4411   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4412                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4413                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4414   {
4415     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4416       {
4417         int eltId1=abs(*desc1)-1;
4418         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4419           {
4420             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4421             if(it==mappRev.end())
4422               {
4423                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4424                 mapp[node]=*it1;
4425                 mappRev[*it1]=node;
4426               }
4427           }
4428       }
4429   }
4430 }
4431
4432 /// @endcond
4433
4434 template<int SPACEDIM>
4435 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4436                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4437 {
4438   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4439   int *eltsIndexPtr(eltsIndex->getPointer());
4440   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4441   const double *bbox(bboxArr->begin());
4442   int nbOfCells=getNumberOfCells();
4443   const int *conn=_nodal_connec->getConstPointer();
4444   const int *connI=_nodal_connec_index->getConstPointer();
4445   double bb[2*SPACEDIM];
4446   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4447   for(int i=0;i<nbOfPoints;i++)
4448     {
4449       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4450       for(int j=0;j<SPACEDIM;j++)
4451         {
4452           bb[2*j]=pos[SPACEDIM*i+j];
4453           bb[2*j+1]=pos[SPACEDIM*i+j];
4454         }
4455       std::vector<int> candidates;
4456       myTree.getIntersectingElems(bb,candidates);
4457       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4458         {
4459           int sz(connI[(*iter)+1]-connI[*iter]-1);
4460           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4461           bool status(false);
4462           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4463             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4464           else
4465             {
4466               if(SPACEDIM!=2)
4467                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4468               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4469               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4470               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4471               INTERP_KERNEL::QuadraticPolygon *pol(0);
4472               for(int j=0;j<sz;j++)
4473                 {
4474                   int nodeId(conn[connI[*iter]+1+j]);
4475                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4476                 }
4477               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4478                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4479               else
4480                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4481               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4482               double a(0.),b(0.),c(0.);
4483               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4484               status=pol->isInOrOut2(n);
4485               delete pol; n->decrRef();
4486             }
4487           if(status)
4488             {
4489               eltsIndexPtr[i+1]++;
4490               elts->pushBackSilent(*iter);
4491             }
4492         }
4493     }
4494 }
4495 /*!
4496  * Finds cells in contact with several balls (i.e. points with precision).
4497  * This method is an extension of getCellContainingPoint() and
4498  * getCellsContainingPoint() for the case of multiple points.
4499  * 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.
4500  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4501  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4502  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4503  *         this->getSpaceDimension() * \a nbOfPoints 
4504  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4505  *  \param [in] eps - radius of balls (i.e. the precision).
4506  *  \param [out] elts - vector returning ids of found cells.
4507  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4508  *         dividing cell ids in \a elts into groups each referring to one
4509  *         point. Its every element (except the last one) is an index pointing to the
4510  *         first id of a group of cells. For example cells in contact with the *i*-th
4511  *         point are described by following range of indices:
4512  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4513  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4514  *         Number of cells in contact with the *i*-th point is
4515  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4516  *  \throw If the coordinates array is not set.
4517  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4518  *
4519  *  \if ENABLE_EXAMPLES
4520  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4521  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4522  *  \endif
4523  */
4524 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4525                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4526 {
4527   int spaceDim=getSpaceDimension();
4528   int mDim=getMeshDimension();
4529   if(spaceDim==3)
4530     {
4531       if(mDim==3)
4532         {
4533           const double *coords=_coords->getConstPointer();
4534           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4535         }
4536       /*else if(mDim==2)
4537         {
4538
4539         }*/
4540       else
4541         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4542     }
4543   else if(spaceDim==2)
4544     {
4545       if(mDim==2)
4546         {
4547           const double *coords=_coords->getConstPointer();
4548           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4549         }
4550       else
4551         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4552     }
4553   else if(spaceDim==1)
4554     {
4555       if(mDim==1)
4556         {
4557           const double *coords=_coords->getConstPointer();
4558           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4559         }
4560       else
4561         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4562     }
4563   else
4564     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4565 }
4566
4567 /*!
4568  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4569  * least two its edges intersect each other anywhere except their extremities. An
4570  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4571  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4572  *         cleared before filling in.
4573  *  \param [in] eps - precision.
4574  *  \throw If \a this->getMeshDimension() != 2.
4575  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4576  */
4577 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4578 {
4579   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4580   if(getMeshDimension()!=2)
4581     throw INTERP_KERNEL::Exception(msg);
4582   int spaceDim=getSpaceDimension();
4583   if(spaceDim!=2 && spaceDim!=3)
4584     throw INTERP_KERNEL::Exception(msg);
4585   const int *conn=_nodal_connec->getConstPointer();
4586   const int *connI=_nodal_connec_index->getConstPointer();
4587   int nbOfCells=getNumberOfCells();
4588   std::vector<double> cell2DinS2;
4589   for(int i=0;i<nbOfCells;i++)
4590     {
4591       int offset=connI[i];
4592       int nbOfNodesForCell=connI[i+1]-offset-1;
4593       if(nbOfNodesForCell<=3)
4594         continue;
4595       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4596       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4597       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4598         cells.push_back(i);
4599       cell2DinS2.clear();
4600     }
4601 }
4602
4603 /*!
4604  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4605  *
4606  * 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.
4607  * 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.
4608  * 
4609  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4610  * This convex envelop is computed using Jarvis march algorithm.
4611  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4612  * 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)
4613  * 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.
4614  *
4615  * \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.
4616  * \sa MEDCouplingUMesh::colinearize2D
4617  */
4618 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4619 {
4620   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4622   checkFullyDefined();
4623   const double *coords=getCoords()->getConstPointer();
4624   int nbOfCells=getNumberOfCells();
4625   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4626   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4627   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4628   int *workIndexOut=nodalConnecIndexOut->getPointer();
4629   *workIndexOut=0;
4630   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4631   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4632   std::set<INTERP_KERNEL::NormalizedCellType> types;
4633   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4634   isChanged->alloc(0,1);
4635   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4636     {
4637       int pos=nodalConnecOut->getNumberOfTuples();
4638       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4639         isChanged->pushBackSilent(i);
4640       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4641       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4642     }
4643   if(isChanged->empty())
4644     return 0;
4645   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4646   _types=types;
4647   return isChanged.retn();
4648 }
4649
4650 /*!
4651  * This method is \b NOT const because it can modify \a this.
4652  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4653  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4654  * \param policy specifies the type of extrusion chosen:
4655  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4656  *   will be repeated to build each level
4657  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4658  *   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
4659  *   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
4660  *   arc.
4661  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4662  */
4663 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4664 {
4665   checkFullyDefined();
4666   mesh1D->checkFullyDefined();
4667   if(!mesh1D->isContiguous1D())
4668     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4669   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4670     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4671   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4672     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4673   if(mesh1D->getMeshDimension()!=1)
4674     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4675   bool isQuad=false;
4676   if(isPresenceOfQuadratic())
4677     {
4678       if(mesh1D->isFullyQuadratic())
4679         isQuad=true;
4680       else
4681         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4682     }
4683   int oldNbOfNodes(getNumberOfNodes());
4684   MCAuto<DataArrayDouble> newCoords;
4685   switch(policy)
4686   {
4687     case 0:
4688       {
4689         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4690         break;
4691       }
4692     case 1:
4693       {
4694         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4695         break;
4696       }
4697     default:
4698       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4699   }
4700   setCoords(newCoords);
4701   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4702   updateTime();
4703   return ret.retn();
4704 }
4705
4706 /*!
4707  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4708  * If it is not the case an exception will be thrown.
4709  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4710  * intersection of plane defined by ('origin','vec').
4711  * This method has one in/out parameter : 'cut3DCurve'.
4712  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4713  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4714  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4715  * This method will throw an exception if \a this contains a non linear segment.
4716  */
4717 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4718 {
4719   checkFullyDefined();
4720   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4722   int ncells=getNumberOfCells();
4723   int nnodes=getNumberOfNodes();
4724   double vec2[3],vec3[3],vec4[3];
4725   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4726   if(normm<1e-6)
4727     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4728   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4729   const int *conn=_nodal_connec->getConstPointer();
4730   const int *connI=_nodal_connec_index->getConstPointer();
4731   const double *coo=_coords->getConstPointer();
4732   std::vector<double> addCoo;
4733   for(int i=0;i<ncells;i++)
4734     {
4735       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4736         {
4737           if(cut3DCurve[i]==-2)
4738             {
4739               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4740               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];
4741               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4742               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4743               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4744                 {
4745                   const double *st2=coo+3*st;
4746                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4747                   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]));
4748                   if(pos>eps && pos<1-eps)
4749                     {
4750                       int nNode=((int)addCoo.size())/3;
4751                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4752                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4753                       cut3DCurve[i]=nnodes+nNode;
4754                     }
4755                 }
4756             }
4757         }
4758       else
4759         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4760     }
4761   if(!addCoo.empty())
4762     {
4763       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4764       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4765       coo2->alloc(newNbOfNodes,3);
4766       double *tmp=coo2->getPointer();
4767       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4768       std::copy(addCoo.begin(),addCoo.end(),tmp);
4769       DataArrayDouble::SetArrayIn(coo2,_coords);
4770     }
4771 }
4772
4773 /*!
4774  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4775  * \param mesh1D is the input 1D mesh used for translation computation.
4776  * \return newCoords new coords filled by this method. 
4777  */
4778 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4779 {
4780   int oldNbOfNodes=getNumberOfNodes();
4781   int nbOf1DCells=mesh1D->getNumberOfCells();
4782   int spaceDim=getSpaceDimension();
4783   DataArrayDouble *ret=DataArrayDouble::New();
4784   std::vector<bool> isQuads;
4785   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4786   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4787   double *retPtr=ret->getPointer();
4788   const double *coords=getCoords()->getConstPointer();
4789   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4790   std::vector<int> v;
4791   std::vector<double> c;
4792   double vec[3];
4793   v.reserve(3);
4794   c.reserve(6);
4795   for(int i=0;i<nbOf1DCells;i++)
4796     {
4797       v.resize(0);
4798       mesh1D->getNodeIdsOfCell(i,v);
4799       c.resize(0);
4800       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4801       mesh1D->getCoordinatesOfNode(v[0],c);
4802       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4803       for(int j=0;j<oldNbOfNodes;j++)
4804         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4805       if(isQuad)
4806         {
4807           c.resize(0);
4808           mesh1D->getCoordinatesOfNode(v[1],c);
4809           mesh1D->getCoordinatesOfNode(v[0],c);
4810           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4811           for(int j=0;j<oldNbOfNodes;j++)
4812             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4813         }
4814     }
4815   ret->copyStringInfoFrom(*getCoords());
4816   return ret;
4817 }
4818
4819 /*!
4820  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4821  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4822  * \return newCoords new coords filled by this method. 
4823  */
4824 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4825 {
4826   if(mesh1D->getSpaceDimension()==2)
4827     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4828   if(mesh1D->getSpaceDimension()==3)
4829     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4830   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4831 }
4832
4833 /*!
4834  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4835  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4836  * \return newCoords new coords filled by this method. 
4837  */
4838 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4839 {
4840   if(isQuad)
4841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4842   int oldNbOfNodes=getNumberOfNodes();
4843   int nbOf1DCells=mesh1D->getNumberOfCells();
4844   if(nbOf1DCells<2)
4845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4846   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4847   int nbOfLevsInVec=nbOf1DCells+1;
4848   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4849   double *retPtr=ret->getPointer();
4850   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4851   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4852   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4853   tmp->setCoords(tmp2);
4854   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4855   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4856   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4857   for(int i=1;i<nbOfLevsInVec;i++)
4858     {
4859       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4860       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4861       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4862       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4863       tmp->translate(vec);
4864       double tmp3[2],radius,alpha,alpha0;
4865       const double *p0=i+1<nbOfLevsInVec?begin:third;
4866       const double *p1=i+1<nbOfLevsInVec?end:begin;
4867       const double *p2=i+1<nbOfLevsInVec?third:end;
4868       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4869       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]);
4870       double angle=acos(cosangle/(radius*radius));
4871       tmp->rotate(end,0,angle);
4872       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4873     }
4874   return ret.retn();
4875 }
4876
4877 /*!
4878  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4879  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4880  * \return newCoords new coords filled by this method. 
4881  */
4882 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4883 {
4884   if(isQuad)
4885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4886   int oldNbOfNodes=getNumberOfNodes();
4887   int nbOf1DCells=mesh1D->getNumberOfCells();
4888   if(nbOf1DCells<2)
4889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4890   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
4891   int nbOfLevsInVec=nbOf1DCells+1;
4892   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4893   double *retPtr=ret->getPointer();
4894   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4895   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4896   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
4897   tmp->setCoords(tmp2);
4898   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4899   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4900   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4901   for(int i=1;i<nbOfLevsInVec;i++)
4902     {
4903       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4904       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4905       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4906       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4907       tmp->translate(vec);
4908       double tmp3[2],radius,alpha,alpha0;
4909       const double *p0=i+1<nbOfLevsInVec?begin:third;
4910       const double *p1=i+1<nbOfLevsInVec?end:begin;
4911       const double *p2=i+1<nbOfLevsInVec?third:end;
4912       double vecPlane[3]={
4913         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4914         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4915         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4916       };
4917       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4918       if(norm>1.e-7)
4919         {
4920           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4921           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4922           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4923           double s2=norm2;
4924           double c2=cos(asin(s2));
4925           double m[3][3]={
4926             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4927             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4928             {-vec2[1]*s2, vec2[0]*s2, c2}
4929           };
4930           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]};
4931           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]};
4932           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]};
4933           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4934           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]);
4935           double angle=acos(cosangle/(radius*radius));
4936           tmp->rotate(end,vecPlane,angle);
4937         }
4938       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4939     }
4940   return ret.retn();
4941 }
4942
4943 /*!
4944  * This method is private because not easy to use for end user. This method is const contrary to
4945  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4946  * the coords sorted slice by slice.
4947  * \param isQuad specifies presence of quadratic cells.
4948  */
4949 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4950 {
4951   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4952   int nbOf2DCells(getNumberOfCells());
4953   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4954   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4955   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4956   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4957   newConnI->alloc(nbOf3DCells+1,1);
4958   int *newConnIPtr(newConnI->getPointer());
4959   *newConnIPtr++=0;
4960   std::vector<int> newc;
4961   for(int j=0;j<nbOf2DCells;j++)
4962     {
4963       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4964       *newConnIPtr++=(int)newc.size();
4965     }
4966   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4967   int *newConnPtr(newConn->getPointer());
4968   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4969   newConnIPtr=newConnI->getPointer();
4970   for(int iz=0;iz<nbOf1DCells;iz++)
4971     {
4972       if(iz!=0)
4973         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4974       const int *posOfTypeOfCell(newConnIPtr);
4975       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4976         {
4977           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4978           if(icell!=*posOfTypeOfCell)
4979             {
4980               if(*iter!=-1)
4981                 *newConnPtr=(*iter)+iz*deltaPerLev;
4982               else
4983                 *newConnPtr=-1;
4984             }
4985           else
4986             {
4987               *newConnPtr=*iter;
4988               posOfTypeOfCell++;
4989             }
4990         }
4991     }
4992   ret->setConnectivity(newConn,newConnI,true);
4993   ret->setCoords(getCoords());
4994   return ret;
4995 }
4996
4997 /*!
4998  * Checks if \a this mesh is constituted by only quadratic cells.
4999  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5000  *  \throw If the coordinates array is not set.
5001  *  \throw If the nodal connectivity of cells is not defined.
5002  */
5003 bool MEDCouplingUMesh::isFullyQuadratic() const
5004 {
5005   checkFullyDefined();
5006   bool ret=true;
5007   int nbOfCells=getNumberOfCells();
5008   for(int i=0;i<nbOfCells && ret;i++)
5009     {
5010       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5011       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5012       ret=cm.isQuadratic();
5013     }
5014   return ret;
5015 }
5016
5017 /*!
5018  * Checks if \a this mesh includes any quadratic cell.
5019  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5020  *  \throw If the coordinates array is not set.
5021  *  \throw If the nodal connectivity of cells is not defined.
5022  */
5023 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5024 {
5025   checkFullyDefined();
5026   bool ret=false;
5027   int nbOfCells=getNumberOfCells();
5028   for(int i=0;i<nbOfCells && !ret;i++)
5029     {
5030       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5031       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5032       ret=cm.isQuadratic();
5033     }
5034   return ret;
5035 }
5036
5037 /*!
5038  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5039  * this mesh, it remains unchanged.
5040  *  \throw If the coordinates array is not set.
5041  *  \throw If the nodal connectivity of cells is not defined.
5042  */
5043 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5044 {
5045   checkFullyDefined();
5046   int nbOfCells=getNumberOfCells();
5047   int delta=0;
5048   const int *iciptr=_nodal_connec_index->getConstPointer();
5049   for(int i=0;i<nbOfCells;i++)
5050     {
5051       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5052       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5053       if(cm.isQuadratic())
5054         {
5055           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5056           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5057           if(!cml.isDynamic())
5058             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5059           else
5060             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5061         }
5062     }
5063   if(delta==0)
5064     return ;
5065   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5066   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5067   const int *icptr=_nodal_connec->getConstPointer();
5068   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5069   newConnI->alloc(nbOfCells+1,1);
5070   int *ocptr=newConn->getPointer();
5071   int *ociptr=newConnI->getPointer();
5072   *ociptr=0;
5073   _types.clear();
5074   for(int i=0;i<nbOfCells;i++,ociptr++)
5075     {
5076       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5077       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5078       if(!cm.isQuadratic())
5079         {
5080           _types.insert(type);
5081           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5082           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5083         }
5084       else
5085         {
5086           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5087           _types.insert(typel);
5088           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5089           int newNbOfNodes=cml.getNumberOfNodes();
5090           if(cml.isDynamic())
5091             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5092           *ocptr++=(int)typel;
5093           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5094           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5095         }
5096     }
5097   setConnectivity(newConn,newConnI,false);
5098 }
5099
5100 /*!
5101  * This method converts all linear cell in \a this to quadratic one.
5102  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5103  * 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)
5104  * 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.
5105  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5106  * end of the existing coordinates.
5107  * 
5108  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5109  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5110  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5111  * 
5112  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5113  *
5114  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5115  */
5116 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5117 {
5118   DataArrayInt *conn=0,*connI=0;
5119   DataArrayDouble *coords=0;
5120   std::set<INTERP_KERNEL::NormalizedCellType> types;
5121   checkFullyDefined();
5122   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5123   MCAuto<DataArrayDouble> coordsSafe;
5124   int meshDim=getMeshDimension();
5125   switch(conversionType)
5126   {
5127     case 0:
5128       switch(meshDim)
5129       {
5130         case 1:
5131           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5132           connSafe=conn; connISafe=connI; coordsSafe=coords;
5133           break;
5134         case 2:
5135           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5136           connSafe=conn; connISafe=connI; coordsSafe=coords;
5137           break;
5138         case 3:
5139           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5140           connSafe=conn; connISafe=connI; coordsSafe=coords;
5141           break;
5142         default:
5143           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5144       }
5145       break;
5146         case 1:
5147           {
5148             switch(meshDim)
5149             {
5150               case 1:
5151                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5152                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5153                 break;
5154               case 2:
5155                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5156                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5157                 break;
5158               case 3:
5159                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5160                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5161                 break;
5162               default:
5163                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5164             }
5165             break;
5166           }
5167         default:
5168           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5169   }
5170   setConnectivity(connSafe,connISafe,false);
5171   _types=types;
5172   setCoords(coordsSafe);
5173   return ret.retn();
5174 }
5175
5176 /*!
5177  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5178  * so that the number of cells remains the same. Quadratic faces are converted to
5179  * polygons. This method works only for 2D meshes in
5180  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5181  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5182  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5183  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5184  *         a polylinized edge constituting the input polygon.
5185  *  \throw If the coordinates array is not set.
5186  *  \throw If the nodal connectivity of cells is not defined.
5187  *  \throw If \a this->getMeshDimension() != 2.
5188  *  \throw If \a this->getSpaceDimension() != 2.
5189  */
5190 void MEDCouplingUMesh::tessellate2D(double eps)
5191 {
5192   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5193   if(spaceDim!=2)
5194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5195   switch(meshDim)
5196     {
5197     case 1:
5198       return tessellate2DCurveInternal(eps);
5199     case 2:
5200       return tessellate2DInternal(eps);
5201     default:
5202       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5203     }
5204 }
5205 /*!
5206  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5207  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5208  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5209  *         a sub-divided edge.
5210  *  \throw If the coordinates array is not set.
5211  *  \throw If the nodal connectivity of cells is not defined.
5212  *  \throw If \a this->getMeshDimension() != 1.
5213  *  \throw If \a this->getSpaceDimension() != 2.
5214  */
5215
5216 #if 0
5217 /*!
5218  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5219  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5220  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5221  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5222  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5223  * This method can be seen as the opposite method of colinearize2D.
5224  * 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
5225  * to avoid to modify the numbering of existing nodes.
5226  *
5227  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5228  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5229  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5230  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5231  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5232  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5233  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5234  *
5235  * \sa buildDescendingConnectivity2
5236  */
5237 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5238                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5239 {
5240   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5242   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5243   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5245   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5247   //DataArrayInt *out0(0),*outi0(0);
5248   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5249   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5250   //out0s=out0s->buildUnique(); out0s->sort(true);
5251 }
5252 #endif
5253
5254 /*!
5255  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5256  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5257  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5258  */
5259 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5260 {
5261   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5262   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5263   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5264   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5265   int nbOfCells=getNumberOfCells();
5266   int nbOfNodes=getNumberOfNodes();
5267   const int *cPtr=_nodal_connec->getConstPointer();
5268   const int *icPtr=_nodal_connec_index->getConstPointer();
5269   int lastVal=0,offset=nbOfNodes;
5270   for(int i=0;i<nbOfCells;i++,icPtr++)
5271     {
5272       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5273       if(type==INTERP_KERNEL::NORM_SEG2)
5274         {
5275           types.insert(INTERP_KERNEL::NORM_SEG3);
5276           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5277           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5278           newConn->pushBackSilent(offset++);
5279           lastVal+=4;
5280           newConnI->pushBackSilent(lastVal);
5281           ret->pushBackSilent(i);
5282         }
5283       else
5284         {
5285           types.insert(type);
5286           lastVal+=(icPtr[1]-icPtr[0]);
5287           newConnI->pushBackSilent(lastVal);
5288           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5289         }
5290     }
5291   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5292   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5293   return ret.retn();
5294 }
5295
5296 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
5297 {
5298   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5299   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5300   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5301   //
5302   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5303   DataArrayInt *conn1D=0,*conn1DI=0;
5304   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5305   DataArrayDouble *coordsTmp=0;
5306   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5307   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5308   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5309   const int *c1DPtr=conn1D->begin();
5310   const int *c1DIPtr=conn1DI->begin();
5311   int nbOfCells=getNumberOfCells();
5312   const int *cPtr=_nodal_connec->getConstPointer();
5313   const int *icPtr=_nodal_connec_index->getConstPointer();
5314   int lastVal=0;
5315   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5316     {
5317       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5318       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5319       if(!cm.isQuadratic())
5320         {
5321           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5322           types.insert(typ2); newConn->pushBackSilent(typ2);
5323           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5324           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5325             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5326           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5327           newConnI->pushBackSilent(lastVal);
5328           ret->pushBackSilent(i);
5329         }
5330       else
5331         {
5332           types.insert(typ);
5333           lastVal+=(icPtr[1]-icPtr[0]);
5334           newConnI->pushBackSilent(lastVal);
5335           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5336         }
5337     }
5338   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5339   return ret.retn();
5340 }
5341
5342 /*!
5343  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5344  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5345  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5346  */
5347 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5348 {
5349   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5350   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5351   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5352 }
5353
5354 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5355 {
5356   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5357   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5358   //
5359   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5360   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5361   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5362   //
5363   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5364   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5365   DataArrayInt *conn1D=0,*conn1DI=0;
5366   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5367   DataArrayDouble *coordsTmp=0;
5368   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5369   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5370   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5371   const int *c1DPtr=conn1D->begin();
5372   const int *c1DIPtr=conn1DI->begin();
5373   int nbOfCells=getNumberOfCells();
5374   const int *cPtr=_nodal_connec->getConstPointer();
5375   const int *icPtr=_nodal_connec_index->getConstPointer();
5376   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5377   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5378     {
5379       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5380       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5381       if(!cm.isQuadratic())
5382         {
5383           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5384           types.insert(typ2); newConn->pushBackSilent(typ2);
5385           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5386           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5387             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5388           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5389           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5390           newConnI->pushBackSilent(lastVal);
5391           ret->pushBackSilent(i);
5392         }
5393       else
5394         {
5395           types.insert(typ);
5396           lastVal+=(icPtr[1]-icPtr[0]);
5397           newConnI->pushBackSilent(lastVal);
5398           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5399         }
5400     }
5401   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5402   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5403   return ret.retn();
5404 }
5405
5406 /*!
5407  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5408  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5409  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5410  */
5411 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5412 {
5413   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5414   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5415   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5416 }
5417
5418 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5419 {
5420   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5421   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5422   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5423   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5424   //
5425   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5426   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5427   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5428   //
5429   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5430   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5431   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5432   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5433   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5434   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5435   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5436   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5437   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5438   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5439   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5440   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5441   int nbOfCells=getNumberOfCells();
5442   const int *cPtr=_nodal_connec->getConstPointer();
5443   const int *icPtr=_nodal_connec_index->getConstPointer();
5444   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5445   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5446     {
5447       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5448       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5449       if(!cm.isQuadratic())
5450         {
5451           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5452           if(typ2==INTERP_KERNEL::NORM_ERROR)
5453             {
5454               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5455               throw INTERP_KERNEL::Exception(oss.str().c_str());
5456             }
5457           types.insert(typ2); newConn->pushBackSilent(typ2);
5458           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5459           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5460             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5461           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5462             {
5463               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5464               int tmpPos=newConn->getNumberOfTuples();
5465               newConn->pushBackSilent(nodeId2);
5466               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5467             }
5468           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5469           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5470           newConnI->pushBackSilent(lastVal);
5471           ret->pushBackSilent(i);
5472         }
5473       else
5474         {
5475           types.insert(typ);
5476           lastVal+=(icPtr[1]-icPtr[0]);
5477           newConnI->pushBackSilent(lastVal);
5478           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5479         }
5480     }
5481   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5482   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5483   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5484   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5485   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5486   int *c=newConn->getPointer();
5487   const int *cI(newConnI->begin());
5488   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5489     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5490   offset=coordsTmp2Safe->getNumberOfTuples();
5491   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5492     c[cI[(*elt)+1]-1]+=offset;
5493   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5494   return ret.retn();
5495 }
5496
5497 /*!
5498  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5499  * In addition, returns an array mapping new cells to old ones. <br>
5500  * This method typically increases the number of cells in \a this mesh
5501  * but the number of nodes remains \b unchanged.
5502  * That's why the 3D splitting policies
5503  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5504  *  \param [in] policy - specifies a pattern used for splitting.
5505  * The semantic of \a policy is:
5506  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5507  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5508  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5509  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5510  *
5511  *
5512  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5513  *          an id of old cell producing it. The caller is to delete this array using
5514  *         decrRef() as it is no more needed.
5515  *
5516  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5517  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5518  *          and \a this->getMeshDimension() != 3. 
5519  *  \throw If \a policy is not one of the four discussed above.
5520  *  \throw If the nodal connectivity of cells is not defined.
5521  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5522  */
5523 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5524 {
5525   switch(policy)
5526   {
5527     case 0:
5528       return simplexizePol0();
5529     case 1:
5530       return simplexizePol1();
5531     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5532         return simplexizePlanarFace5();
5533     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5534         return simplexizePlanarFace6();
5535     default:
5536       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)");
5537   }
5538 }
5539
5540 /*!
5541  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5542  * - 1D: INTERP_KERNEL::NORM_SEG2
5543  * - 2D: INTERP_KERNEL::NORM_TRI3
5544  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5545  *
5546  * This method is useful for users that need to use P1 field services as
5547  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5548  * All these methods need mesh support containing only simplex cells.
5549  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5550  *  \throw If the coordinates array is not set.
5551  *  \throw If the nodal connectivity of cells is not defined.
5552  *  \throw If \a this->getMeshDimension() < 1.
5553  */
5554 bool MEDCouplingUMesh::areOnlySimplexCells() const
5555 {
5556   checkFullyDefined();
5557   int mdim=getMeshDimension();
5558   if(mdim<1 || mdim>3)
5559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5560   int nbCells=getNumberOfCells();
5561   const int *conn=_nodal_connec->getConstPointer();
5562   const int *connI=_nodal_connec_index->getConstPointer();
5563   for(int i=0;i<nbCells;i++)
5564     {
5565       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5566       if(!cm.isSimplex())
5567         return false;
5568     }
5569   return true;
5570 }
5571
5572 /*!
5573  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5574  */
5575 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5576 {
5577   checkConnectivityFullyDefined();
5578   if(getMeshDimension()!=2)
5579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5580   int nbOfCells=getNumberOfCells();
5581   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5582   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5583   ret->alloc(nbOfCells+nbOfCutCells,1);
5584   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5585   int *retPt=ret->getPointer();
5586   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5587   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5588   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5589   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5590   int *pt=newConn->getPointer();
5591   int *ptI=newConnI->getPointer();
5592   ptI[0]=0;
5593   const int *oldc=_nodal_connec->getConstPointer();
5594   const int *ci=_nodal_connec_index->getConstPointer();
5595   for(int i=0;i<nbOfCells;i++,ci++)
5596     {
5597       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5598         {
5599           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5600             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5601           pt=std::copy(tmp,tmp+8,pt);
5602           ptI[1]=ptI[0]+4;
5603           ptI[2]=ptI[0]+8;
5604           *retPt++=i;
5605           *retPt++=i;
5606           ptI+=2;
5607         }
5608       else
5609         {
5610           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5611           ptI[1]=ptI[0]+ci[1]-ci[0];
5612           ptI++;
5613           *retPt++=i;
5614         }
5615     }
5616   _nodal_connec->decrRef();
5617   _nodal_connec=newConn.retn();
5618   _nodal_connec_index->decrRef();
5619   _nodal_connec_index=newConnI.retn();
5620   computeTypes();
5621   updateTime();
5622   return ret.retn();
5623 }
5624
5625 /*!
5626  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5627  */
5628 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5629 {
5630   checkConnectivityFullyDefined();
5631   if(getMeshDimension()!=2)
5632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5633   int nbOfCells=getNumberOfCells();
5634   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5635   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5636   ret->alloc(nbOfCells+nbOfCutCells,1);
5637   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5638   int *retPt=ret->getPointer();
5639   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5640   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5641   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5642   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5643   int *pt=newConn->getPointer();
5644   int *ptI=newConnI->getPointer();
5645   ptI[0]=0;
5646   const int *oldc=_nodal_connec->getConstPointer();
5647   const int *ci=_nodal_connec_index->getConstPointer();
5648   for(int i=0;i<nbOfCells;i++,ci++)
5649     {
5650       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5651         {
5652           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5653             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5654           pt=std::copy(tmp,tmp+8,pt);
5655           ptI[1]=ptI[0]+4;
5656           ptI[2]=ptI[0]+8;
5657           *retPt++=i;
5658           *retPt++=i;
5659           ptI+=2;
5660         }
5661       else
5662         {
5663           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5664           ptI[1]=ptI[0]+ci[1]-ci[0];
5665           ptI++;
5666           *retPt++=i;
5667         }
5668     }
5669   _nodal_connec->decrRef();
5670   _nodal_connec=newConn.retn();
5671   _nodal_connec_index->decrRef();
5672   _nodal_connec_index=newConnI.retn();
5673   computeTypes();
5674   updateTime();
5675   return ret.retn();
5676 }
5677
5678 /*!
5679  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5680  */
5681 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5682 {
5683   checkConnectivityFullyDefined();
5684   if(getMeshDimension()!=3)
5685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5686   int nbOfCells=getNumberOfCells();
5687   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5688   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5689   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5690   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5691   int *retPt=ret->getPointer();
5692   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5693   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5694   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5695   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5696   int *pt=newConn->getPointer();
5697   int *ptI=newConnI->getPointer();
5698   ptI[0]=0;
5699   const int *oldc=_nodal_connec->getConstPointer();
5700   const int *ci=_nodal_connec_index->getConstPointer();
5701   for(int i=0;i<nbOfCells;i++,ci++)
5702     {
5703       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5704         {
5705           for(int j=0;j<5;j++,pt+=5,ptI++)
5706             {
5707               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5708               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];
5709               *retPt++=i;
5710               ptI[1]=ptI[0]+5;
5711             }
5712         }
5713       else
5714         {
5715           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5716           ptI[1]=ptI[0]+ci[1]-ci[0];
5717           ptI++;
5718           *retPt++=i;
5719         }
5720     }
5721   _nodal_connec->decrRef();
5722   _nodal_connec=newConn.retn();
5723   _nodal_connec_index->decrRef();
5724   _nodal_connec_index=newConnI.retn();
5725   computeTypes();
5726   updateTime();
5727   return ret.retn();
5728 }
5729
5730 /*!
5731  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5732  */
5733 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5734 {
5735   checkConnectivityFullyDefined();
5736   if(getMeshDimension()!=3)
5737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5738   int nbOfCells=getNumberOfCells();
5739   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5740   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5741   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5742   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5743   int *retPt=ret->getPointer();
5744   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5745   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5746   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5747   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5748   int *pt=newConn->getPointer();
5749   int *ptI=newConnI->getPointer();
5750   ptI[0]=0;
5751   const int *oldc=_nodal_connec->getConstPointer();
5752   const int *ci=_nodal_connec_index->getConstPointer();
5753   for(int i=0;i<nbOfCells;i++,ci++)
5754     {
5755       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5756         {
5757           for(int j=0;j<6;j++,pt+=5,ptI++)
5758             {
5759               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5760               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];
5761               *retPt++=i;
5762               ptI[1]=ptI[0]+5;
5763             }
5764         }
5765       else
5766         {
5767           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5768           ptI[1]=ptI[0]+ci[1]-ci[0];
5769           ptI++;
5770           *retPt++=i;
5771         }
5772     }
5773   _nodal_connec->decrRef();
5774   _nodal_connec=newConn.retn();
5775   _nodal_connec_index->decrRef();
5776   _nodal_connec_index=newConnI.retn();
5777   computeTypes();
5778   updateTime();
5779   return ret.retn();
5780 }
5781
5782 /*!
5783  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5784  * so that the number of cells remains the same. Quadratic faces are converted to
5785  * polygons. This method works only for 2D meshes in
5786  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5787  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5788  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5789  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5790  *         a polylinized edge constituting the input polygon.
5791  *  \throw If the coordinates array is not set.
5792  *  \throw If the nodal connectivity of cells is not defined.
5793  *  \throw If \a this->getMeshDimension() != 2.
5794  *  \throw If \a this->getSpaceDimension() != 2.
5795  */
5796 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5797 {
5798   checkFullyDefined();
5799   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5800     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5801   double epsa=fabs(eps);
5802   if(epsa<std::numeric_limits<double>::min())
5803     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 !");
5804   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
5805   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
5806   revDesc1=0; revDescIndx1=0;
5807   mDesc->tessellate2D(eps);
5808   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5809   setCoords(mDesc->getCoords());
5810 }
5811
5812 /*!
5813  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5814  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5815  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5816  *         a sub-divided edge.
5817  *  \throw If the coordinates array is not set.
5818  *  \throw If the nodal connectivity of cells is not defined.
5819  *  \throw If \a this->getMeshDimension() != 1.
5820  *  \throw If \a this->getSpaceDimension() != 2.
5821  */
5822 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
5823 {
5824   checkFullyDefined();
5825   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5827   double epsa=fabs(eps);
5828   if(epsa<std::numeric_limits<double>::min())
5829     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 !");
5830   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5831   int nbCells=getNumberOfCells();
5832   int nbNodes=getNumberOfNodes();
5833   const int *conn=_nodal_connec->getConstPointer();
5834   const int *connI=_nodal_connec_index->getConstPointer();
5835   const double *coords=_coords->getConstPointer();
5836   std::vector<double> addCoo;
5837   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5838   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
5839   newConnI->alloc(nbCells+1,1);
5840   int *newConnIPtr=newConnI->getPointer();
5841   *newConnIPtr=0;
5842   int tmp1[3];
5843   INTERP_KERNEL::Node *tmp2[3];
5844   std::set<INTERP_KERNEL::NormalizedCellType> types;
5845   for(int i=0;i<nbCells;i++,newConnIPtr++)
5846     {
5847       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5848       if(cm.isQuadratic())
5849         {//assert(connI[i+1]-connI[i]-1==3)
5850           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5851           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5852           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5853           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5854           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5855           if(eac)
5856             {
5857               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5858               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5859               delete eac;
5860               newConnIPtr[1]=(int)newConn.size();
5861             }
5862           else
5863             {
5864               types.insert(INTERP_KERNEL::NORM_SEG2);
5865               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5866               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5867               newConnIPtr[1]=newConnIPtr[0]+3;
5868             }
5869         }
5870       else
5871         {
5872           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5873           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5874           newConnIPtr[1]=newConnIPtr[0]+3;
5875         }
5876     }
5877   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5878     return ;
5879   _types=types;
5880   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5881   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
5882   newConnArr->alloc((int)newConn.size(),1);
5883   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5884   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5885   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
5886   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5887   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5888   std::copy(addCoo.begin(),addCoo.end(),work);
5889   DataArrayDouble::SetArrayIn(newCoords,_coords);
5890   updateTime();
5891 }
5892
5893 /*!
5894  * 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.
5895  * This method completly ignore coordinates.
5896  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5897  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5898  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5899  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5900  */
5901 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5902 {
5903   checkFullyDefined();
5904   if(getMeshDimension()!=2)
5905     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5906   int nbOfCells=getNumberOfCells();
5907   int *connI=_nodal_connec_index->getPointer();
5908   int newConnLgth=0;
5909   for(int i=0;i<nbOfCells;i++,connI++)
5910     {
5911       int offset=descIndex[i];
5912       int nbOfEdges=descIndex[i+1]-offset;
5913       //
5914       bool ddirect=desc[offset+nbOfEdges-1]>0;
5915       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5916       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5917       for(int j=0;j<nbOfEdges;j++)
5918         {
5919           bool direct=desc[offset+j]>0;
5920           int edgeId=std::abs(desc[offset+j])-1;
5921           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5922             {
5923               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5924               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5925               int ref2=direct?id1:id2;
5926               if(ref==ref2)
5927                 {
5928                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5929                   newConnLgth+=nbOfSubNodes-1;
5930                   ref=direct?id2:id1;
5931                 }
5932               else
5933                 {
5934                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5935                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5936                 }
5937             }
5938           else
5939             {
5940               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5941             }
5942         }
5943       newConnLgth++;//+1 is for cell type
5944       connI[1]=newConnLgth;
5945     }
5946   //
5947   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5948   newConn->alloc(newConnLgth,1);
5949   int *work=newConn->getPointer();
5950   for(int i=0;i<nbOfCells;i++)
5951     {
5952       *work++=INTERP_KERNEL::NORM_POLYGON;
5953       int offset=descIndex[i];
5954       int nbOfEdges=descIndex[i+1]-offset;
5955       for(int j=0;j<nbOfEdges;j++)
5956         {
5957           bool direct=desc[offset+j]>0;
5958           int edgeId=std::abs(desc[offset+j])-1;
5959           if(direct)
5960             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5961           else
5962             {
5963               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5964               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5965               work=std::copy(it,it+nbOfSubNodes-1,work);
5966             }
5967         }
5968     }
5969   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5970   _types.clear();
5971   if(nbOfCells>0)
5972     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5973 }
5974
5975 /*!
5976  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5977  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5978  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5979  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5980  * so it can be useful to call mergeNodes() before calling this method.
5981  *  \throw If \a this->getMeshDimension() <= 1.
5982  *  \throw If the coordinates array is not set.
5983  *  \throw If the nodal connectivity of cells is not defined.
5984  */
5985 void MEDCouplingUMesh::convertDegeneratedCells()
5986 {
5987   checkFullyDefined();
5988   if(getMeshDimension()<=1)
5989     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5990   int nbOfCells=getNumberOfCells();
5991   if(nbOfCells<1)
5992     return ;
5993   int initMeshLgth=getNodalConnectivityArrayLen();
5994   int *conn=_nodal_connec->getPointer();
5995   int *index=_nodal_connec_index->getPointer();
5996   int posOfCurCell=0;
5997   int newPos=0;
5998   int lgthOfCurCell;
5999   for(int i=0;i<nbOfCells;i++)
6000     {
6001       lgthOfCurCell=index[i+1]-posOfCurCell;
6002       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6003       int newLgth;
6004       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6005                                                                                                      conn+newPos+1,newLgth);
6006       conn[newPos]=newType;
6007       newPos+=newLgth+1;
6008       posOfCurCell=index[i+1];
6009       index[i+1]=newPos;
6010     }
6011   if(newPos!=initMeshLgth)
6012     _nodal_connec->reAlloc(newPos);
6013   computeTypes();
6014 }
6015
6016 /*!
6017  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6018  * A cell is considered to be oriented correctly if an angle between its
6019  * normal vector and a given vector is less than \c PI / \c 2.
6020  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6021  *         cells. 
6022  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6023  *         checked.
6024  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6025  *         is not cleared before filling in.
6026  *  \throw If \a this->getMeshDimension() != 2.
6027  *  \throw If \a this->getSpaceDimension() != 3.
6028  *
6029  *  \if ENABLE_EXAMPLES
6030  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6031  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6032  *  \endif
6033  */
6034 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6035 {
6036   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6037     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6038   int nbOfCells=getNumberOfCells();
6039   const int *conn=_nodal_connec->getConstPointer();
6040   const int *connI=_nodal_connec_index->getConstPointer();
6041   const double *coordsPtr=_coords->getConstPointer();
6042   for(int i=0;i<nbOfCells;i++)
6043     {
6044       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6045       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6046         {
6047           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6048           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6049             cells.push_back(i);
6050         }
6051     }
6052 }
6053
6054 /*!
6055  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6056  * considered to be oriented correctly if an angle between its normal vector and a
6057  * given vector is less than \c PI / \c 2. 
6058  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6059  *         cells. 
6060  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6061  *         checked.
6062  *  \throw If \a this->getMeshDimension() != 2.
6063  *  \throw If \a this->getSpaceDimension() != 3.
6064  *
6065  *  \if ENABLE_EXAMPLES
6066  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6067  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6068  *  \endif
6069  *
6070  *  \sa changeOrientationOfCells
6071  */
6072 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6073 {
6074   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6075     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6076   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6077   const int *connI(_nodal_connec_index->getConstPointer());
6078   const double *coordsPtr(_coords->getConstPointer());
6079   bool isModified(false);
6080   for(int i=0;i<nbOfCells;i++)
6081     {
6082       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6083       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6084         {
6085           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6086           bool isQuadratic(cm.isQuadratic());
6087           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6088             {
6089               isModified=true;
6090               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6091             }
6092         }
6093     }
6094   if(isModified)
6095     _nodal_connec->declareAsNew();
6096   updateTime();
6097 }
6098
6099 /*!
6100  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6101  *
6102  * \sa orientCorrectly2DCells
6103  */
6104 void MEDCouplingUMesh::changeOrientationOfCells()
6105 {
6106   int mdim(getMeshDimension());
6107   if(mdim!=2 && mdim!=1)
6108     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6109   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6110   const int *connI(_nodal_connec_index->getConstPointer());
6111   if(mdim==2)
6112     {//2D
6113       for(int i=0;i<nbOfCells;i++)
6114         {
6115           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6116           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6117           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6118         }
6119     }
6120   else
6121     {//1D
6122       for(int i=0;i<nbOfCells;i++)
6123         {
6124           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6125           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6126           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6127         }
6128     }
6129 }
6130
6131 /*!
6132  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6133  * oriented facets. The normal vector of the facet should point out of the cell.
6134  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6135  *         is not cleared before filling in.
6136  *  \throw If \a this->getMeshDimension() != 3.
6137  *  \throw If \a this->getSpaceDimension() != 3.
6138  *  \throw If the coordinates array is not set.
6139  *  \throw If the nodal connectivity of cells is not defined.
6140  *
6141  *  \if ENABLE_EXAMPLES
6142  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6143  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6144  *  \endif
6145  */
6146 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6147 {
6148   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6149     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6150   int nbOfCells=getNumberOfCells();
6151   const int *conn=_nodal_connec->getConstPointer();
6152   const int *connI=_nodal_connec_index->getConstPointer();
6153   const double *coordsPtr=_coords->getConstPointer();
6154   for(int i=0;i<nbOfCells;i++)
6155     {
6156       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6157       if(type==INTERP_KERNEL::NORM_POLYHED)
6158         {
6159           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6160             cells.push_back(i);
6161         }
6162     }
6163 }
6164
6165 /*!
6166  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6167  * out of the cell. 
6168  *  \throw If \a this->getMeshDimension() != 3.
6169  *  \throw If \a this->getSpaceDimension() != 3.
6170  *  \throw If the coordinates array is not set.
6171  *  \throw If the nodal connectivity of cells is not defined.
6172  *  \throw If the reparation fails.
6173  *
6174  *  \if ENABLE_EXAMPLES
6175  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6176  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6177  *  \endif
6178  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6179  */
6180 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6181 {
6182   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6183     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6184   int nbOfCells=getNumberOfCells();
6185   int *conn=_nodal_connec->getPointer();
6186   const int *connI=_nodal_connec_index->getConstPointer();
6187   const double *coordsPtr=_coords->getConstPointer();
6188   for(int i=0;i<nbOfCells;i++)
6189     {
6190       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6191       if(type==INTERP_KERNEL::NORM_POLYHED)
6192         {
6193           try
6194           {
6195               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6196                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6197           }
6198           catch(INTERP_KERNEL::Exception& e)
6199           {
6200               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6201               throw INTERP_KERNEL::Exception(oss.str().c_str());
6202           }
6203         }
6204     }
6205   updateTime();
6206 }
6207
6208 /*!
6209  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6210  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6211  * according to which the first facet of the cell should be oriented to have the normal vector
6212  * pointing out of cell.
6213  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6214  *         cells. The caller is to delete this array using decrRef() as it is no more
6215  *         needed. 
6216  *  \throw If \a this->getMeshDimension() != 3.
6217  *  \throw If \a this->getSpaceDimension() != 3.
6218  *  \throw If the coordinates array is not set.
6219  *  \throw If the nodal connectivity of cells is not defined.
6220  *
6221  *  \if ENABLE_EXAMPLES
6222  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6223  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6224  *  \endif
6225  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6226  */
6227 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6228 {
6229   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6230   if(getMeshDimension()!=3)
6231     throw INTERP_KERNEL::Exception(msg);
6232   int spaceDim=getSpaceDimension();
6233   if(spaceDim!=3)
6234     throw INTERP_KERNEL::Exception(msg);
6235   //
6236   int nbOfCells=getNumberOfCells();
6237   int *conn=_nodal_connec->getPointer();
6238   const int *connI=_nodal_connec_index->getConstPointer();
6239   const double *coo=getCoords()->getConstPointer();
6240   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6241   for(int i=0;i<nbOfCells;i++)
6242     {
6243       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6244       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6245         {
6246           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6247             {
6248               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6249               cells->pushBackSilent(i);
6250             }
6251         }
6252     }
6253   return cells.retn();
6254 }
6255
6256 /*!
6257  * This method is a faster method to correct orientation of all 3D cells in \a this.
6258  * 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.
6259  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6260  * 
6261  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6262  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6263  */
6264 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6265 {
6266   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6267     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6268   int nbOfCells=getNumberOfCells();
6269   int *conn=_nodal_connec->getPointer();
6270   const int *connI=_nodal_connec_index->getConstPointer();
6271   const double *coordsPtr=_coords->getConstPointer();
6272   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6273   for(int i=0;i<nbOfCells;i++)
6274     {
6275       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6276       switch(type)
6277       {
6278         case INTERP_KERNEL::NORM_TETRA4:
6279           {
6280             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6281               {
6282                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6283                 ret->pushBackSilent(i);
6284               }
6285             break;
6286           }
6287         case INTERP_KERNEL::NORM_PYRA5:
6288           {
6289             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6290               {
6291                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6292                 ret->pushBackSilent(i);
6293               }
6294             break;
6295           }
6296         case INTERP_KERNEL::NORM_PENTA6:
6297         case INTERP_KERNEL::NORM_HEXA8:
6298         case INTERP_KERNEL::NORM_HEXGP12:
6299           {
6300             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6301               {
6302                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6303                 ret->pushBackSilent(i);
6304               }
6305             break;
6306           }
6307         case INTERP_KERNEL::NORM_POLYHED:
6308           {
6309             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6310               {
6311                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6312                 ret->pushBackSilent(i);
6313               }
6314             break;
6315           }
6316         default:
6317           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 !");
6318       }
6319     }
6320   updateTime();
6321   return ret.retn();
6322 }
6323
6324 /*!
6325  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6326  * If it is not the case an exception will be thrown.
6327  * This method is fast because the first cell of \a this is used to compute the plane.
6328  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6329  * \param pos output of size at least 3 used to store a point owned of searched plane.
6330  */
6331 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6332 {
6333   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6334     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6335   const int *conn=_nodal_connec->getConstPointer();
6336   const int *connI=_nodal_connec_index->getConstPointer();
6337   const double *coordsPtr=_coords->getConstPointer();
6338   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6339   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6340 }
6341
6342 /*!
6343  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6344  * cells. Currently cells of the following types are treated:
6345  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6346  * For a cell of other type an exception is thrown.
6347  * Space dimension of a 2D mesh can be either 2 or 3.
6348  * The Edge Ratio of a cell \f$t\f$ is: 
6349  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6350  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6351  *  the smallest edge lengths of \f$t\f$.
6352  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6353  *          cells and one time, lying on \a this mesh. The caller is to delete this
6354  *          field using decrRef() as it is no more needed. 
6355  *  \throw If the coordinates array is not set.
6356  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6357  *  \throw If the connectivity data array has more than one component.
6358  *  \throw If the connectivity data array has a named component.
6359  *  \throw If the connectivity index data array has more than one component.
6360  *  \throw If the connectivity index data array has a named component.
6361  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6362  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6363  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6364  */
6365 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6366 {
6367   checkConsistencyLight();
6368   int spaceDim=getSpaceDimension();
6369   int meshDim=getMeshDimension();
6370   if(spaceDim!=2 && spaceDim!=3)
6371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6372   if(meshDim!=2 && meshDim!=3)
6373     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6374   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6375   ret->setMesh(this);
6376   int nbOfCells=getNumberOfCells();
6377   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6378   arr->alloc(nbOfCells,1);
6379   double *pt=arr->getPointer();
6380   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6381   const int *conn=_nodal_connec->getConstPointer();
6382   const int *connI=_nodal_connec_index->getConstPointer();
6383   const double *coo=_coords->getConstPointer();
6384   double tmp[12];
6385   for(int i=0;i<nbOfCells;i++,pt++)
6386     {
6387       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6388       switch(t)
6389       {
6390         case INTERP_KERNEL::NORM_TRI3:
6391           {
6392             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6393             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6394             break;
6395           }
6396         case INTERP_KERNEL::NORM_QUAD4:
6397           {
6398             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6399             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6400             break;
6401           }
6402         case INTERP_KERNEL::NORM_TETRA4:
6403           {
6404             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6405             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6406             break;
6407           }
6408         default:
6409           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6410       }
6411       conn+=connI[i+1]-connI[i];
6412     }
6413   ret->setName("EdgeRatio");
6414   ret->synchronizeTimeWithSupport();
6415   return ret.retn();
6416 }
6417
6418 /*!
6419  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6420  * cells. Currently cells of the following types are treated:
6421  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6422  * For a cell of other type an exception is thrown.
6423  * Space dimension of a 2D mesh can be either 2 or 3.
6424  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6425  *          cells and one time, lying on \a this mesh. The caller is to delete this
6426  *          field using decrRef() as it is no more needed. 
6427  *  \throw If the coordinates array is not set.
6428  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6429  *  \throw If the connectivity data array has more than one component.
6430  *  \throw If the connectivity data array has a named component.
6431  *  \throw If the connectivity index data array has more than one component.
6432  *  \throw If the connectivity index data array has a named component.
6433  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6434  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6435  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6436  */
6437 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6438 {
6439   checkConsistencyLight();
6440   int spaceDim=getSpaceDimension();
6441   int meshDim=getMeshDimension();
6442   if(spaceDim!=2 && spaceDim!=3)
6443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6444   if(meshDim!=2 && meshDim!=3)
6445     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6446   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6447   ret->setMesh(this);
6448   int nbOfCells=getNumberOfCells();
6449   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6450   arr->alloc(nbOfCells,1);
6451   double *pt=arr->getPointer();
6452   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6453   const int *conn=_nodal_connec->getConstPointer();
6454   const int *connI=_nodal_connec_index->getConstPointer();
6455   const double *coo=_coords->getConstPointer();
6456   double tmp[12];
6457   for(int i=0;i<nbOfCells;i++,pt++)
6458     {
6459       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6460       switch(t)
6461       {
6462         case INTERP_KERNEL::NORM_TRI3:
6463           {
6464             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6465             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6466             break;
6467           }
6468         case INTERP_KERNEL::NORM_QUAD4:
6469           {
6470             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6471             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6472             break;
6473           }
6474         case INTERP_KERNEL::NORM_TETRA4:
6475           {
6476             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6477             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6478             break;
6479           }
6480         default:
6481           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6482       }
6483       conn+=connI[i+1]-connI[i];
6484     }
6485   ret->setName("AspectRatio");
6486   ret->synchronizeTimeWithSupport();
6487   return ret.retn();
6488 }
6489
6490 /*!
6491  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6492  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
6493  * in 3D space. Currently only cells of the following types are
6494  * treated: INTERP_KERNEL::NORM_QUAD4.
6495  * For a cell of other type an exception is thrown.
6496  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
6497  * Defining
6498  * \f$t=\vec{da}\times\vec{ab}\f$,
6499  * \f$u=\vec{ab}\times\vec{bc}\f$
6500  * \f$v=\vec{bc}\times\vec{cd}\f$
6501  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
6502  *  \f[
6503  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
6504  *  \f]
6505  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6506  *          cells and one time, lying on \a this mesh. The caller is to delete this
6507  *          field using decrRef() as it is no more needed. 
6508  *  \throw If the coordinates array is not set.
6509  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6510  *  \throw If the connectivity data array has more than one component.
6511  *  \throw If the connectivity data array has a named component.
6512  *  \throw If the connectivity index data array has more than one component.
6513  *  \throw If the connectivity index data array has a named component.
6514  *  \throw If \a this->getMeshDimension() != 2.
6515  *  \throw If \a this->getSpaceDimension() != 3.
6516  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6517  */
6518 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6519 {
6520   checkConsistencyLight();
6521   int spaceDim=getSpaceDimension();
6522   int meshDim=getMeshDimension();
6523   if(spaceDim!=3)
6524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6525   if(meshDim!=2)
6526     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6527   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6528   ret->setMesh(this);
6529   int nbOfCells=getNumberOfCells();
6530   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6531   arr->alloc(nbOfCells,1);
6532   double *pt=arr->getPointer();
6533   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6534   const int *conn=_nodal_connec->getConstPointer();
6535   const int *connI=_nodal_connec_index->getConstPointer();
6536   const double *coo=_coords->getConstPointer();
6537   double tmp[12];
6538   for(int i=0;i<nbOfCells;i++,pt++)
6539     {
6540       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6541       switch(t)
6542       {
6543         case INTERP_KERNEL::NORM_QUAD4:
6544           {
6545             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6546             *pt=INTERP_KERNEL::quadWarp(tmp);
6547             break;
6548           }
6549         default:
6550           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6551       }
6552       conn+=connI[i+1]-connI[i];
6553     }
6554   ret->setName("Warp");
6555   ret->synchronizeTimeWithSupport();
6556   return ret.retn();
6557 }
6558
6559
6560 /*!
6561  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6562  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6563  * treated: INTERP_KERNEL::NORM_QUAD4.
6564  * The skew is computed as follow for a quad with points (a,b,c,d): let
6565  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
6566  * then the skew is computed as:
6567  *  \f[
6568  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
6569  *  \f]
6570  *
6571  * For a cell of other type an exception is thrown.
6572  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6573  *          cells and one time, lying on \a this mesh. The caller is to delete this
6574  *          field using decrRef() as it is no more needed. 
6575  *  \throw If the coordinates array is not set.
6576  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6577  *  \throw If the connectivity data array has more than one component.
6578  *  \throw If the connectivity data array has a named component.
6579  *  \throw If the connectivity index data array has more than one component.
6580  *  \throw If the connectivity index data array has a named component.
6581  *  \throw If \a this->getMeshDimension() != 2.
6582  *  \throw If \a this->getSpaceDimension() != 3.
6583  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6584  */
6585 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6586 {
6587   checkConsistencyLight();
6588   int spaceDim=getSpaceDimension();
6589   int meshDim=getMeshDimension();
6590   if(spaceDim!=3)
6591     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6592   if(meshDim!=2)
6593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6594   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6595   ret->setMesh(this);
6596   int nbOfCells=getNumberOfCells();
6597   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6598   arr->alloc(nbOfCells,1);
6599   double *pt=arr->getPointer();
6600   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6601   const int *conn=_nodal_connec->getConstPointer();
6602   const int *connI=_nodal_connec_index->getConstPointer();
6603   const double *coo=_coords->getConstPointer();
6604   double tmp[12];
6605   for(int i=0;i<nbOfCells;i++,pt++)
6606     {
6607       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6608       switch(t)
6609       {
6610         case INTERP_KERNEL::NORM_QUAD4:
6611           {
6612             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6613             *pt=INTERP_KERNEL::quadSkew(tmp);
6614             break;
6615           }
6616         default:
6617           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6618       }
6619       conn+=connI[i+1]-connI[i];
6620     }
6621   ret->setName("Skew");
6622   ret->synchronizeTimeWithSupport();
6623   return ret.retn();
6624 }
6625
6626 /*!
6627  * 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.
6628  *
6629  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6630  *
6631  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6632  */
6633 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6634 {
6635   checkConsistencyLight();
6636   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6637   ret->setMesh(this);
6638   std::set<INTERP_KERNEL::NormalizedCellType> types;
6639   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6640   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6641   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6642   arr->alloc(nbCells,1);
6643   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6644     {
6645       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6646       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6647       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6648     }
6649   ret->setArray(arr);
6650   ret->setName("Diameter");
6651   return ret.retn();
6652 }
6653
6654 /*!
6655  * This method aggregate the bbox of each cell and put it into bbox parameter.
6656  * 
6657  * \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)
6658  *                         For all other cases this input parameter is ignored.
6659  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6660  * 
6661  * \throw If \a this is not fully set (coordinates and connectivity).
6662  * \throw If a cell in \a this has no valid nodeId.
6663  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6664  */
6665 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6666 {
6667   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6668   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.
6669     return getBoundingBoxForBBTreeFast();
6670   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6671     {
6672       bool presenceOfQuadratic(false);
6673       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6674         {
6675           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6676           if(cm.isQuadratic())
6677             presenceOfQuadratic=true;
6678         }
6679       if(!presenceOfQuadratic)
6680         return getBoundingBoxForBBTreeFast();
6681       if(mDim==2 && sDim==2)
6682         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6683       else
6684         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6685     }
6686   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) !");
6687 }
6688
6689 /*!
6690  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6691  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6692  * 
6693  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6694  * 
6695  * \throw If \a this is not fully set (coordinates and connectivity).
6696  * \throw If a cell in \a this has no valid nodeId.
6697  */
6698 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6699 {
6700   checkFullyDefined();
6701   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6702   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6703   double *bbox(ret->getPointer());
6704   for(int i=0;i<nbOfCells*spaceDim;i++)
6705     {
6706       bbox[2*i]=std::numeric_limits<double>::max();
6707       bbox[2*i+1]=-std::numeric_limits<double>::max();
6708     }
6709   const double *coordsPtr(_coords->getConstPointer());
6710   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6711   for(int i=0;i<nbOfCells;i++)
6712     {
6713       int offset=connI[i]+1;
6714       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6715       for(int j=0;j<nbOfNodesForCell;j++)
6716         {
6717           int nodeId=conn[offset+j];
6718           if(nodeId>=0 && nodeId<nbOfNodes)
6719             {
6720               for(int k=0;k<spaceDim;k++)
6721                 {
6722                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6723                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6724                 }
6725               kk++;
6726             }
6727         }
6728       if(kk==0)
6729         {
6730           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6731           throw INTERP_KERNEL::Exception(oss.str().c_str());
6732         }
6733     }
6734   return ret.retn();
6735 }
6736
6737 /*!
6738  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6739  * useful for 2D meshes having quadratic cells
6740  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6741  * the two extremities of the arc of circle).
6742  * 
6743  * \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)
6744  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6745  * \throw If \a this is not fully defined.
6746  * \throw If \a this is not a mesh with meshDimension equal to 2.
6747  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6748  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6749  */
6750 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6751 {
6752   checkFullyDefined();
6753   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6754   if(spaceDim!=2 || mDim!=2)
6755     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!");
6756   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6757   double *bbox(ret->getPointer());
6758   const double *coords(_coords->getConstPointer());
6759   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6760   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6761     {
6762       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6763       int sz(connI[1]-connI[0]-1);
6764       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6765       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6766       INTERP_KERNEL::QuadraticPolygon *pol(0);
6767       for(int j=0;j<sz;j++)
6768         {
6769           int nodeId(conn[*connI+1+j]);
6770           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6771         }
6772       if(!cm.isQuadratic())
6773         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6774       else
6775         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6776       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6777       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6778     }
6779   return ret.retn();
6780 }
6781
6782 /*!
6783  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6784  * useful for 2D meshes having quadratic cells
6785  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6786  * the two extremities of the arc of circle).
6787  * 
6788  * \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)
6789  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6790  * \throw If \a this is not fully defined.
6791  * \throw If \a this is not a mesh with meshDimension equal to 1.
6792  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6793  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6794  */
6795 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6796 {
6797   checkFullyDefined();
6798   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6799   if(spaceDim!=2 || mDim!=1)
6800     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!");
6801   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6802   double *bbox(ret->getPointer());
6803   const double *coords(_coords->getConstPointer());
6804   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6805   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6806     {
6807       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6808       int sz(connI[1]-connI[0]-1);
6809       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6810       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6811       INTERP_KERNEL::Edge *edge(0);
6812       for(int j=0;j<sz;j++)
6813         {
6814           int nodeId(conn[*connI+1+j]);
6815           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6816         }
6817       if(!cm.isQuadratic())
6818         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6819       else
6820         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6821       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6822       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6823     }
6824   return ret.retn();
6825 }
6826
6827 /// @cond INTERNAL
6828
6829 namespace MEDCouplingImpl
6830 {
6831   class ConnReader
6832   {
6833   public:
6834     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6835     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6836   private:
6837     const int *_conn;
6838     int _val;
6839   };
6840
6841   class ConnReader2
6842   {
6843   public:
6844     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6845     bool operator() (const int& pos) { return _conn[pos]==_val; }
6846   private:
6847     const int *_conn;
6848     int _val;
6849   };
6850 }
6851
6852 /// @endcond
6853
6854 /*!
6855  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6856  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6857  * \a this is composed in cell types.
6858  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6859  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6860  * This parameter is kept only for compatibility with other methode listed above.
6861  */
6862 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6863 {
6864   checkConnectivityFullyDefined();
6865   const int *conn=_nodal_connec->getConstPointer();
6866   const int *connI=_nodal_connec_index->getConstPointer();
6867   const int *work=connI;
6868   int nbOfCells=getNumberOfCells();
6869   std::size_t n=getAllGeoTypes().size();
6870   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6871   std::set<INTERP_KERNEL::NormalizedCellType> types;
6872   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6873     {
6874       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6875       if(types.find(typ)!=types.end())
6876         {
6877           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6878           oss << " is not contiguous !";
6879           throw INTERP_KERNEL::Exception(oss.str().c_str());
6880         }
6881       types.insert(typ);
6882       ret[3*i]=typ;
6883       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
6884       ret[3*i+1]=(int)std::distance(work,work2);
6885       work=work2;
6886     }
6887   return ret;
6888 }
6889
6890 /*!
6891  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6892  * only for types cell, type node is not managed.
6893  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6894  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6895  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6896  * If 2 or more same geometric type is in \a code and exception is thrown too.
6897  *
6898  * This method firstly checks
6899  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6900  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6901  * an exception is thrown too.
6902  * 
6903  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6904  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6905  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6906  */
6907 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6908 {
6909   if(code.empty())
6910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6911   std::size_t sz=code.size();
6912   std::size_t n=sz/3;
6913   if(sz%3!=0)
6914     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6915   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6916   int nb=0;
6917   bool isNoPflUsed=true;
6918   for(std::size_t i=0;i<n;i++)
6919     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6920       {
6921         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6922         nb+=code[3*i+1];
6923         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6924           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6925         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6926       }
6927   if(types.size()!=n)
6928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6929   if(isNoPflUsed)
6930     {
6931       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6932         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6933       if(types.size()==_types.size())
6934         return 0;
6935     }
6936   MCAuto<DataArrayInt> ret=DataArrayInt::New();
6937   ret->alloc(nb,1);
6938   int *retPtr=ret->getPointer();
6939   const int *connI=_nodal_connec_index->getConstPointer();
6940   const int *conn=_nodal_connec->getConstPointer();
6941   int nbOfCells=getNumberOfCells();
6942   const int *i=connI;
6943   int kk=0;
6944   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6945     {
6946       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
6947       int offset=(int)std::distance(connI,i);
6948       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
6949       int nbOfCellsOfCurType=(int)std::distance(i,j);
6950       if(code[3*kk+2]==-1)
6951         for(int k=0;k<nbOfCellsOfCurType;k++)
6952           *retPtr++=k+offset;
6953       else
6954         {
6955           int idInIdsPerType=code[3*kk+2];
6956           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6957             {
6958               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6959               if(zePfl)
6960                 {
6961                   zePfl->checkAllocated();
6962                   if(zePfl->getNumberOfComponents()==1)
6963                     {
6964                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6965                         {
6966                           if(*k>=0 && *k<nbOfCellsOfCurType)
6967                             *retPtr=(*k)+offset;
6968                           else
6969                             {
6970                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6971                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6972                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6973                             }
6974                         }
6975                     }
6976                   else
6977                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6978                 }
6979               else
6980                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6981             }
6982           else
6983             {
6984               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6985               oss << " should be in [0," << idsPerType.size() << ") !";
6986               throw INTERP_KERNEL::Exception(oss.str().c_str());
6987             }
6988         }
6989       i=j;
6990     }
6991   return ret.retn();
6992 }
6993
6994 /*!
6995  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6996  * 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.
6997  * 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.
6998  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6999  * 
7000  * \param [in] profile
7001  * \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.
7002  * \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,
7003  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7004  * \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.
7005  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7006  * \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
7007  */
7008 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7009 {
7010   if(!profile)
7011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7012   if(profile->getNumberOfComponents()!=1)
7013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7014   checkConnectivityFullyDefined();
7015   const int *conn=_nodal_connec->getConstPointer();
7016   const int *connI=_nodal_connec_index->getConstPointer();
7017   int nbOfCells=getNumberOfCells();
7018   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7019   std::vector<int> typeRangeVals(1);
7020   for(const int *i=connI;i!=connI+nbOfCells;)
7021     {
7022       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7023       if(std::find(types.begin(),types.end(),curType)!=types.end())
7024         {
7025           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7026         }
7027       types.push_back(curType);
7028       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7029       typeRangeVals.push_back((int)std::distance(connI,i));
7030     }
7031   //
7032   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7033   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7034   MCAuto<DataArrayInt> tmp0=castArr;
7035   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7036   MCAuto<DataArrayInt> tmp2=castsPresent;
7037   //
7038   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7039   code.resize(3*nbOfCastsFinal);
7040   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7041   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7042   for(int i=0;i<nbOfCastsFinal;i++)
7043     {
7044       int castId=castsPresent->getIJ(i,0);
7045       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7046       idsInPflPerType2.push_back(tmp3);
7047       code[3*i]=(int)types[castId];
7048       code[3*i+1]=tmp3->getNumberOfTuples();
7049       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7050       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7051         {
7052           tmp4->copyStringInfoFrom(*profile);
7053           idsPerType2.push_back(tmp4);
7054           code[3*i+2]=(int)idsPerType2.size()-1;
7055         }
7056       else
7057         {
7058           code[3*i+2]=-1;
7059         }
7060     }
7061   std::size_t sz2=idsInPflPerType2.size();
7062   idsInPflPerType.resize(sz2);
7063   for(std::size_t i=0;i<sz2;i++)
7064     {
7065       DataArrayInt *locDa=idsInPflPerType2[i];
7066       locDa->incrRef();
7067       idsInPflPerType[i]=locDa;
7068     }
7069   std::size_t sz=idsPerType2.size();
7070   idsPerType.resize(sz);
7071   for(std::size_t i=0;i<sz;i++)
7072     {
7073       DataArrayInt *locDa=idsPerType2[i];
7074       locDa->incrRef();
7075       idsPerType[i]=locDa;
7076     }
7077 }
7078
7079 /*!
7080  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7081  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7082  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7083  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
7084  */
7085 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7086 {
7087   checkFullyDefined();
7088   nM1LevMesh->checkFullyDefined();
7089   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7090     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7091   if(_coords!=nM1LevMesh->getCoords())
7092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7093   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7094   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7095   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7096   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7097   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7098   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7099   tmp->setConnectivity(tmp0,tmp1);
7100   tmp->renumberCells(ret0->getConstPointer(),false);
7101   revDesc=tmp->getNodalConnectivity();
7102   revDescIndx=tmp->getNodalConnectivityIndex();
7103   DataArrayInt *ret=0;
7104   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7105     {
7106       int tmp2;
7107       ret->getMaxValue(tmp2);
7108       ret->decrRef();
7109       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7110       throw INTERP_KERNEL::Exception(oss.str().c_str());
7111     }
7112   nM1LevMeshIds=ret;
7113   //
7114   revDesc->incrRef();
7115   revDescIndx->incrRef();
7116   ret1->incrRef();
7117   ret0->incrRef();
7118   meshnM1Old2New=ret0;
7119   return ret1;
7120 }
7121
7122 /*!
7123  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7124  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7125  * in "Old to New" mode.
7126  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7127  *          this array using decrRef() as it is no more needed.
7128  *  \throw If the nodal connectivity of cells is not defined.
7129  */
7130 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7131 {
7132   checkConnectivityFullyDefined();
7133   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7134   renumberCells(ret->getConstPointer(),false);
7135   return ret.retn();
7136 }
7137
7138 /*!
7139  * This methods checks that cells are sorted by their types.
7140  * This method makes asumption (no check) that connectivity is correctly set before calling.
7141  */
7142 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7143 {
7144   checkFullyDefined();
7145   const int *conn=_nodal_connec->getConstPointer();
7146   const int *connI=_nodal_connec_index->getConstPointer();
7147   int nbOfCells=getNumberOfCells();
7148   std::set<INTERP_KERNEL::NormalizedCellType> types;
7149   for(const int *i=connI;i!=connI+nbOfCells;)
7150     {
7151       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7152       if(types.find(curType)!=types.end())
7153         return false;
7154       types.insert(curType);
7155       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7156     }
7157   return true;
7158 }
7159
7160 /*!
7161  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7162  * The geometric type order is specified by MED file.
7163  * 
7164  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7165  */
7166 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7167 {
7168   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7169 }
7170
7171 /*!
7172  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7173  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7174  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7175  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7176  */
7177 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7178 {
7179   checkFullyDefined();
7180   const int *conn=_nodal_connec->getConstPointer();
7181   const int *connI=_nodal_connec_index->getConstPointer();
7182   int nbOfCells=getNumberOfCells();
7183   if(nbOfCells==0)
7184     return true;
7185   int lastPos=-1;
7186   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7187   for(const int *i=connI;i!=connI+nbOfCells;)
7188     {
7189       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7190       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7191       if(isTypeExists!=orderEnd)
7192         {
7193           int pos=(int)std::distance(orderBg,isTypeExists);
7194           if(pos<=lastPos)
7195             return false;
7196           lastPos=pos;
7197           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7198         }
7199       else
7200         {
7201           if(sg.find(curType)==sg.end())
7202             {
7203               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7204               sg.insert(curType);
7205             }
7206           else
7207             return false;
7208         }
7209     }
7210   return true;
7211 }
7212
7213 /*!
7214  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7215  * 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
7216  * 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'.
7217  */
7218 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7219 {
7220   checkConnectivityFullyDefined();
7221   int nbOfCells=getNumberOfCells();
7222   const int *conn=_nodal_connec->getConstPointer();
7223   const int *connI=_nodal_connec_index->getConstPointer();
7224   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7225   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7226   tmpa->alloc(nbOfCells,1);
7227   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7228   tmpb->fillWithZero();
7229   int *tmp=tmpa->getPointer();
7230   int *tmp2=tmpb->getPointer();
7231   for(const int *i=connI;i!=connI+nbOfCells;i++)
7232     {
7233       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7234       if(where!=orderEnd)
7235         {
7236           int pos=(int)std::distance(orderBg,where);
7237           tmp2[pos]++;
7238           tmp[std::distance(connI,i)]=pos;
7239         }
7240       else
7241         {
7242           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7243           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7244           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7245           throw INTERP_KERNEL::Exception(oss.str().c_str());
7246         }
7247     }
7248   nbPerType=tmpb.retn();
7249   return tmpa.retn();
7250 }
7251
7252 /*!
7253  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7254  *
7255  * \return a new object containing the old to new correspondance.
7256  *
7257  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7258  */
7259 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7260 {
7261   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7262 }
7263
7264 /*!
7265  * 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.
7266  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7267  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7268  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7269  */
7270 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7271 {
7272   DataArrayInt *nbPerType=0;
7273   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7274   nbPerType->decrRef();
7275   return tmpa->buildPermArrPerLevel();
7276 }
7277
7278 /*!
7279  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7280  * The number of cells remains unchanged after the call of this method.
7281  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7282  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7283  *
7284  * \return the array giving the correspondance old to new.
7285  */
7286 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7287 {
7288   checkFullyDefined();
7289   computeTypes();
7290   const int *conn=_nodal_connec->getConstPointer();
7291   const int *connI=_nodal_connec_index->getConstPointer();
7292   int nbOfCells=getNumberOfCells();
7293   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7294   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7295     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7296       {
7297         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7298         types.push_back(curType);
7299         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7300       }
7301   DataArrayInt *ret=DataArrayInt::New();
7302   ret->alloc(nbOfCells,1);
7303   int *retPtr=ret->getPointer();
7304   std::fill(retPtr,retPtr+nbOfCells,-1);
7305   int newCellId=0;
7306   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7307     {
7308       for(const int *i=connI;i!=connI+nbOfCells;i++)
7309         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7310           retPtr[std::distance(connI,i)]=newCellId++;
7311     }
7312   renumberCells(retPtr,false);
7313   return ret;
7314 }
7315
7316 /*!
7317  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7318  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7319  * This method makes asumption that connectivity is correctly set before calling.
7320  */
7321 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7322 {
7323   checkConnectivityFullyDefined();
7324   const int *conn=_nodal_connec->getConstPointer();
7325   const int *connI=_nodal_connec_index->getConstPointer();
7326   int nbOfCells=getNumberOfCells();
7327   std::vector<MEDCouplingUMesh *> ret;
7328   for(const int *i=connI;i!=connI+nbOfCells;)
7329     {
7330       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7331       int beginCellId=(int)std::distance(connI,i);
7332       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7333       int endCellId=(int)std::distance(connI,i);
7334       int sz=endCellId-beginCellId;
7335       int *cells=new int[sz];
7336       for(int j=0;j<sz;j++)
7337         cells[j]=beginCellId+j;
7338       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7339       delete [] cells;
7340       ret.push_back(m);
7341     }
7342   return ret;
7343 }
7344
7345 /*!
7346  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7347  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7348  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7349  *
7350  * \return a newly allocated instance, that the caller must manage.
7351  * \throw If \a this contains more than one geometric type.
7352  * \throw If the nodal connectivity of \a this is not fully defined.
7353  * \throw If the internal data is not coherent.
7354  */
7355 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7356 {
7357   checkConnectivityFullyDefined();
7358   if(_types.size()!=1)
7359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7360   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7361   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7362   ret->setCoords(getCoords());
7363   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7364   if(retC)
7365     {
7366       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7367       retC->setNodalConnectivity(c);
7368     }
7369   else
7370     {
7371       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7372       if(!retD)
7373         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7374       DataArrayInt *c=0,*ci=0;
7375       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7376       MCAuto<DataArrayInt> cs(c),cis(ci);
7377       retD->setNodalConnectivity(cs,cis);
7378     }
7379   return ret.retn();
7380 }
7381
7382 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7383 {
7384   checkConnectivityFullyDefined();
7385   if(_types.size()!=1)
7386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7387   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7388   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7389   if(cm.isDynamic())
7390     {
7391       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7392       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7393       throw INTERP_KERNEL::Exception(oss.str().c_str());
7394     }
7395   int nbCells=getNumberOfCells();
7396   int typi=(int)typ;
7397   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7398   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7399   int *outPtr=connOut->getPointer();
7400   const int *conn=_nodal_connec->begin();
7401   const int *connI=_nodal_connec_index->begin();
7402   nbNodesPerCell++;
7403   for(int i=0;i<nbCells;i++,connI++)
7404     {
7405       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7406         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7407       else
7408         {
7409           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 << ") !";
7410           throw INTERP_KERNEL::Exception(oss.str().c_str());
7411         }
7412     }
7413   return connOut.retn();
7414 }
7415
7416 /*!
7417  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7418  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7419  * \param nodalConn
7420  * \param nodalConnI
7421  */
7422 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7423 {
7424   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7425   checkConnectivityFullyDefined();
7426   if(_types.size()!=1)
7427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7428   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7429   if(lgth<nbCells)
7430     throw INTERP_KERNEL::Exception(msg0);
7431   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7432   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7433   int *cp(c->getPointer()),*cip(ci->getPointer());
7434   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7435   cip[0]=0;
7436   for(int i=0;i<nbCells;i++,cip++,incip++)
7437     {
7438       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7439       int delta(stop-strt);
7440       if(delta>=1)
7441         {
7442           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7443             cp=std::copy(incp+strt,incp+stop,cp);
7444           else
7445             throw INTERP_KERNEL::Exception(msg0);
7446         }
7447       else
7448         throw INTERP_KERNEL::Exception(msg0);
7449       cip[1]=cip[0]+delta;
7450     }
7451   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7452 }
7453
7454 /*!
7455  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7456  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7457  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7458  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7459  * are not used here to avoid the build of big permutation array.
7460  *
7461  * \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
7462  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7463  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7464  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7465  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7466  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7467  * \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
7468  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7469  */
7470 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7471                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7472                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7473 {
7474   std::vector<const MEDCouplingUMesh *> ms2;
7475   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7476     if(*it)
7477       {
7478         (*it)->checkConnectivityFullyDefined();
7479         ms2.push_back(*it);
7480       }
7481   if(ms2.empty())
7482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7483   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7484   int meshDim=ms2[0]->getMeshDimension();
7485   std::vector<const MEDCouplingUMesh *> m1ssm;
7486   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7487   //
7488   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7489   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7490   int fake=0,rk=0;
7491   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7492   ret1->alloc(0,1); ret2->alloc(0,1);
7493   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7494     {
7495       if(meshDim!=(*it)->getMeshDimension())
7496         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7497       if(refCoo!=(*it)->getCoords())
7498         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7499       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7500       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7501       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7502       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7503         {
7504           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7505           m1ssmSingleAuto.push_back(singleCell);
7506           m1ssmSingle.push_back(singleCell);
7507           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7508         }
7509     }
7510   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7511   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7512   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7513   for(std::size_t i=0;i<m1ssm.size();i++)
7514     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7515   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7516   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7517   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7518   return ret0.retn();
7519 }
7520
7521 /*!
7522  * This method returns a newly created DataArrayInt instance.
7523  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7524  */
7525 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7526 {
7527   checkFullyDefined();
7528   const int *conn=_nodal_connec->getConstPointer();
7529   const int *connIndex=_nodal_connec_index->getConstPointer();
7530   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7531   for(const int *w=begin;w!=end;w++)
7532     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7533       ret->pushBackSilent(*w);
7534   return ret.retn();
7535 }
7536
7537 /*!
7538  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7539  * are in [0:getNumberOfCells())
7540  */
7541 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7542 {
7543   checkFullyDefined();
7544   const int *conn=_nodal_connec->getConstPointer();
7545   const int *connI=_nodal_connec_index->getConstPointer();
7546   int nbOfCells=getNumberOfCells();
7547   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7548   int *tmp=new int[nbOfCells];
7549   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7550     {
7551       int j=0;
7552       for(const int *i=connI;i!=connI+nbOfCells;i++)
7553         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7554           tmp[std::distance(connI,i)]=j++;
7555     }
7556   DataArrayInt *ret=DataArrayInt::New();
7557   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7558   ret->copyStringInfoFrom(*da);
7559   int *retPtr=ret->getPointer();
7560   const int *daPtr=da->getConstPointer();
7561   int nbOfElems=da->getNbOfElems();
7562   for(int k=0;k<nbOfElems;k++)
7563     retPtr[k]=tmp[daPtr[k]];
7564   delete [] tmp;
7565   return ret;
7566 }
7567
7568 /*!
7569  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7570  * This method \b works \b for mesh sorted by type.
7571  * cells whose ids is in 'idsPerGeoType' array.
7572  * This method conserves coords and name of mesh.
7573  */
7574 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7575 {
7576   std::vector<int> code=getDistributionOfTypes();
7577   std::size_t nOfTypesInThis=code.size()/3;
7578   int sz=0,szOfType=0;
7579   for(std::size_t i=0;i<nOfTypesInThis;i++)
7580     {
7581       if(code[3*i]!=type)
7582         sz+=code[3*i+1];
7583       else
7584         szOfType=code[3*i+1];
7585     }
7586   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7587     if(*work<0 || *work>=szOfType)
7588       {
7589         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7590         oss << ". It should be in [0," << szOfType << ") !";
7591         throw INTERP_KERNEL::Exception(oss.str().c_str());
7592       }
7593   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7594   int *idsPtr=idsTokeep->getPointer();
7595   int offset=0;
7596   for(std::size_t i=0;i<nOfTypesInThis;i++)
7597     {
7598       if(code[3*i]!=type)
7599         for(int j=0;j<code[3*i+1];j++)
7600           *idsPtr++=offset+j;
7601       else
7602         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7603       offset+=code[3*i+1];
7604     }
7605   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7606   ret->copyTinyInfoFrom(this);
7607   return ret.retn();
7608 }
7609
7610 /*!
7611  * This method returns a vector of size 'this->getNumberOfCells()'.
7612  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7613  */
7614 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7615 {
7616   int ncell=getNumberOfCells();
7617   std::vector<bool> ret(ncell);
7618   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7619   const int *c=getNodalConnectivity()->getConstPointer();
7620   for(int i=0;i<ncell;i++)
7621     {
7622       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7623       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7624       ret[i]=cm.isQuadratic();
7625     }
7626   return ret;
7627 }
7628
7629 /*!
7630  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7631  */
7632 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7633 {
7634   if(other->getType()!=UNSTRUCTURED)
7635     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7636   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7637   return MergeUMeshes(this,otherC);
7638 }
7639
7640 /*!
7641  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7642  * computed by averaging coordinates of cell nodes, so this method is not a right
7643  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7644  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7645  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7646  *          components. The caller is to delete this array using decrRef() as it is
7647  *          no more needed.
7648  *  \throw If the coordinates array is not set.
7649  *  \throw If the nodal connectivity of cells is not defined.
7650  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7651  */
7652 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7653 {
7654   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7655   int spaceDim=getSpaceDimension();
7656   int nbOfCells=getNumberOfCells();
7657   ret->alloc(nbOfCells,spaceDim);
7658   ret->copyStringInfoFrom(*getCoords());
7659   double *ptToFill=ret->getPointer();
7660   const int *nodal=_nodal_connec->getConstPointer();
7661   const int *nodalI=_nodal_connec_index->getConstPointer();
7662   const double *coor=_coords->getConstPointer();
7663   for(int i=0;i<nbOfCells;i++)
7664     {
7665       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7666       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7667       ptToFill+=spaceDim;
7668     }
7669   return ret.retn();
7670 }
7671
7672 /*!
7673  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7674  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7675  * 
7676  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7677  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7678  * 
7679  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7680  * \throw If \a this is not fully defined (coordinates and connectivity)
7681  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7682  */
7683 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7684 {
7685   checkFullyDefined();
7686   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7687   int spaceDim=getSpaceDimension();
7688   int nbOfCells=getNumberOfCells();
7689   int nbOfNodes=getNumberOfNodes();
7690   ret->alloc(nbOfCells,spaceDim);
7691   double *ptToFill=ret->getPointer();
7692   const int *nodal=_nodal_connec->getConstPointer();
7693   const int *nodalI=_nodal_connec_index->getConstPointer();
7694   const double *coor=_coords->getConstPointer();
7695   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7696     {
7697       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7698       std::fill(ptToFill,ptToFill+spaceDim,0.);
7699       if(type!=INTERP_KERNEL::NORM_POLYHED)
7700         {
7701           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7702             {
7703               if(*conn>=0 && *conn<nbOfNodes)
7704                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7705               else
7706                 {
7707                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7708                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7709                 }
7710             }
7711           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7712           if(nbOfNodesInCell>0)
7713             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7714           else
7715             {
7716               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7717               throw INTERP_KERNEL::Exception(oss.str().c_str());
7718             }
7719         }
7720       else
7721         {
7722           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7723           s.erase(-1);
7724           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7725             {
7726               if(*it>=0 && *it<nbOfNodes)
7727                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7728               else
7729                 {
7730                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7731                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7732                 }
7733             }
7734           if(!s.empty())
7735             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7736           else
7737             {
7738               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7739               throw INTERP_KERNEL::Exception(oss.str().c_str());
7740             }
7741         }
7742     }
7743   return ret.retn();
7744 }
7745
7746 /*!
7747  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7748  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7749  * are specified via an array of cell ids. 
7750  *  \warning Validity of the specified cell ids is not checked! 
7751  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7752  *  \param [in] begin - an array of cell ids of interest.
7753  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7754  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7755  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7756  *          caller is to delete this array using decrRef() as it is no more needed. 
7757  *  \throw If the coordinates array is not set.
7758  *  \throw If the nodal connectivity of cells is not defined.
7759  *
7760  *  \if ENABLE_EXAMPLES
7761  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7762  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7763  *  \endif
7764  */
7765 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7766 {
7767   DataArrayDouble *ret=DataArrayDouble::New();
7768   int spaceDim=getSpaceDimension();
7769   int nbOfTuple=(int)std::distance(begin,end);
7770   ret->alloc(nbOfTuple,spaceDim);
7771   double *ptToFill=ret->getPointer();
7772   double *tmp=new double[spaceDim];
7773   const int *nodal=_nodal_connec->getConstPointer();
7774   const int *nodalI=_nodal_connec_index->getConstPointer();
7775   const double *coor=_coords->getConstPointer();
7776   for(const int *w=begin;w!=end;w++)
7777     {
7778       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7779       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7780       ptToFill+=spaceDim;
7781     }
7782   delete [] tmp;
7783   return ret;
7784 }
7785
7786 /*!
7787  * 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".
7788  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7789  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7790  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7791  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7792  * 
7793  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7794  * \throw If spaceDim!=3 or meshDim!=2.
7795  * \throw If connectivity of \a this is invalid.
7796  * \throw If connectivity of a cell in \a this points to an invalid node.
7797  */
7798 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7799 {
7800   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7801   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7802   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7804   ret->alloc(nbOfCells,4);
7805   double *retPtr(ret->getPointer());
7806   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7807   const double *coor(_coords->begin());
7808   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7809     {
7810       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7811       if(nodalI[1]-nodalI[0]>=3)
7812         {
7813           for(int j=0;j<3;j++)
7814             {
7815               int nodeId(nodal[nodalI[0]+1+j]);
7816               if(nodeId>=0 && nodeId<nbOfNodes)
7817                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7818               else
7819                 {
7820                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7821                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7822                 }
7823             }
7824         }
7825       else
7826         {
7827           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7828           throw INTERP_KERNEL::Exception(oss.str().c_str());
7829         }
7830       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7831       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7832     }
7833   return ret.retn();
7834 }
7835
7836 /*!
7837  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7838  * 
7839  */
7840 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7841 {
7842   if(!da)
7843     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7844   da->checkAllocated();
7845   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7846   ret->setCoords(da);
7847   int nbOfTuples=da->getNumberOfTuples();
7848   MCAuto<DataArrayInt> c=DataArrayInt::New();
7849   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7850   c->alloc(2*nbOfTuples,1);
7851   cI->alloc(nbOfTuples+1,1);
7852   int *cp=c->getPointer();
7853   int *cip=cI->getPointer();
7854   *cip++=0;
7855   for(int i=0;i<nbOfTuples;i++)
7856     {
7857       *cp++=INTERP_KERNEL::NORM_POINT1;
7858       *cp++=i;
7859       *cip++=2*(i+1);
7860     }
7861   ret->setConnectivity(c,cI,true);
7862   return ret.retn();
7863 }
7864 /*!
7865  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7866  * Cells and nodes of
7867  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7868  *  \param [in] mesh1 - the first mesh.
7869  *  \param [in] mesh2 - the second mesh.
7870  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7871  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7872  *          is no more needed.
7873  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7874  *  \throw If the coordinates array is not set in none of the meshes.
7875  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7876  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7877  */
7878 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7879 {
7880   std::vector<const MEDCouplingUMesh *> tmp(2);
7881   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7882   return MergeUMeshes(tmp);
7883 }
7884
7885 /*!
7886  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7887  * Cells and nodes of
7888  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7889  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7890  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7891  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7892  *          is no more needed.
7893  *  \throw If \a a.size() == 0.
7894  *  \throw If \a a[ *i* ] == NULL.
7895  *  \throw If the coordinates array is not set in none of the meshes.
7896  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7897  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7898  */
7899 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7900 {
7901   std::size_t sz=a.size();
7902   if(sz==0)
7903     return MergeUMeshesLL(a);
7904   for(std::size_t ii=0;ii<sz;ii++)
7905     if(!a[ii])
7906       {
7907         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7908         throw INTERP_KERNEL::Exception(oss.str().c_str());
7909       }
7910   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
7911   std::vector< const MEDCouplingUMesh * > aa(sz);
7912   int spaceDim=-3;
7913   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7914     {
7915       const MEDCouplingUMesh *cur=a[i];
7916       const DataArrayDouble *coo=cur->getCoords();
7917       if(coo)
7918         spaceDim=coo->getNumberOfComponents();
7919     }
7920   if(spaceDim==-3)
7921     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7922   for(std::size_t i=0;i<sz;i++)
7923     {
7924       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7925       aa[i]=bb[i];
7926     }
7927   return MergeUMeshesLL(aa);
7928 }
7929
7930 /// @cond INTERNAL
7931
7932 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7933 {
7934   if(a.empty())
7935     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7936   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7937   int meshDim=(*it)->getMeshDimension();
7938   int nbOfCells=(*it)->getNumberOfCells();
7939   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
7940   for(;it!=a.end();it++)
7941     {
7942       if(meshDim!=(*it)->getMeshDimension())
7943         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7944       nbOfCells+=(*it)->getNumberOfCells();
7945       meshLgth+=(*it)->getNodalConnectivityArrayLen();
7946     }
7947   std::vector<const MEDCouplingPointSet *> aps(a.size());
7948   std::copy(a.begin(),a.end(),aps.begin());
7949   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
7950   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7951   ret->setCoords(pts);
7952   MCAuto<DataArrayInt> c=DataArrayInt::New();
7953   c->alloc(meshLgth,1);
7954   int *cPtr=c->getPointer();
7955   MCAuto<DataArrayInt> cI=DataArrayInt::New();
7956   cI->alloc(nbOfCells+1,1);
7957   int *cIPtr=cI->getPointer();
7958   *cIPtr++=0;
7959   int offset=0;
7960   int offset2=0;
7961   for(it=a.begin();it!=a.end();it++)
7962     {
7963       int curNbOfCell=(*it)->getNumberOfCells();
7964       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7965       const int *curC=(*it)->_nodal_connec->getConstPointer();
7966       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7967       for(int j=0;j<curNbOfCell;j++)
7968         {
7969           const int *src=curC+curCI[j];
7970           *cPtr++=*src++;
7971           for(;src!=curC+curCI[j+1];src++,cPtr++)
7972             {
7973               if(*src!=-1)
7974                 *cPtr=*src+offset2;
7975               else
7976                 *cPtr=-1;
7977             }
7978         }
7979       offset+=curCI[curNbOfCell];
7980       offset2+=(*it)->getNumberOfNodes();
7981     }
7982   //
7983   ret->setConnectivity(c,cI,true);
7984   return ret.retn();
7985 }
7986
7987 /// @endcond
7988
7989 /*!
7990  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7991  * dimension and sharing the node coordinates array.
7992  * All cells of the first mesh precede all cells of the second mesh
7993  * within the result mesh. 
7994  *  \param [in] mesh1 - the first mesh.
7995  *  \param [in] mesh2 - the second mesh.
7996  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7997  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7998  *          is no more needed.
7999  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8000  *  \throw If the meshes do not share the node coordinates array.
8001  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8002  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8003  */
8004 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8005 {
8006   std::vector<const MEDCouplingUMesh *> tmp(2);
8007   tmp[0]=mesh1; tmp[1]=mesh2;
8008   return MergeUMeshesOnSameCoords(tmp);
8009 }
8010
8011 /*!
8012  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8013  * dimension and sharing the node coordinates array.
8014  * All cells of the *i*-th mesh precede all cells of the
8015  * (*i*+1)-th mesh within the result mesh.
8016  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8017  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8018  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8019  *          is no more needed.
8020  *  \throw If \a a.size() == 0.
8021  *  \throw If \a a[ *i* ] == NULL.
8022  *  \throw If the meshes do not share the node coordinates array.
8023  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8024  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8025  */
8026 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8027 {
8028   if(meshes.empty())
8029     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8030   for(std::size_t ii=0;ii<meshes.size();ii++)
8031     if(!meshes[ii])
8032       {
8033         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8034         throw INTERP_KERNEL::Exception(oss.str().c_str());
8035       }
8036   const DataArrayDouble *coords=meshes.front()->getCoords();
8037   int meshDim=meshes.front()->getMeshDimension();
8038   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8039   int meshLgth=0;
8040   int meshIndexLgth=0;
8041   for(;iter!=meshes.end();iter++)
8042     {
8043       if(coords!=(*iter)->getCoords())
8044         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8045       if(meshDim!=(*iter)->getMeshDimension())
8046         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8047       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8048       meshIndexLgth+=(*iter)->getNumberOfCells();
8049     }
8050   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8051   nodal->alloc(meshLgth,1);
8052   int *nodalPtr=nodal->getPointer();
8053   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8054   nodalIndex->alloc(meshIndexLgth+1,1);
8055   int *nodalIndexPtr=nodalIndex->getPointer();
8056   int offset=0;
8057   for(iter=meshes.begin();iter!=meshes.end();iter++)
8058     {
8059       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8060       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8061       int nbOfCells=(*iter)->getNumberOfCells();
8062       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8063       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8064       if(iter!=meshes.begin())
8065         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8066       else
8067         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8068       offset+=meshLgth2;
8069     }
8070   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8071   ret->setName("merge");
8072   ret->setMeshDimension(meshDim);
8073   ret->setConnectivity(nodal,nodalIndex,true);
8074   ret->setCoords(coords);
8075   return ret;
8076 }
8077
8078 /*!
8079  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8080  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8081  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8082  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8083  * New" mode are returned for each input mesh.
8084  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8085  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8086  *          valid values [0,1,2], see zipConnectivityTraducer().
8087  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8088  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8089  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8090  *          no more needed.
8091  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8092  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8093  *          is no more needed.
8094  *  \throw If \a meshes.size() == 0.
8095  *  \throw If \a meshes[ *i* ] == NULL.
8096  *  \throw If the meshes do not share the node coordinates array.
8097  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8098  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8099  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8100  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8101  */
8102 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8103 {
8104   //All checks are delegated to MergeUMeshesOnSameCoords
8105   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8106   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8107   corr.resize(meshes.size());
8108   std::size_t nbOfMeshes=meshes.size();
8109   int offset=0;
8110   const int *o2nPtr=o2n->getConstPointer();
8111   for(std::size_t i=0;i<nbOfMeshes;i++)
8112     {
8113       DataArrayInt *tmp=DataArrayInt::New();
8114       int curNbOfCells=meshes[i]->getNumberOfCells();
8115       tmp->alloc(curNbOfCells,1);
8116       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8117       offset+=curNbOfCells;
8118       tmp->setName(meshes[i]->getName());
8119       corr[i]=tmp;
8120     }
8121   return ret.retn();
8122 }
8123
8124 /*!
8125  * Makes all given meshes share the nodal connectivity array. The common connectivity
8126  * array is created by concatenating the connectivity arrays of all given meshes. All
8127  * the given meshes must be of the same space dimension but dimension of cells **can
8128  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8129  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8130  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8131  *  \param [in,out] meshes - a vector of meshes to update.
8132  *  \throw If any of \a meshes is NULL.
8133  *  \throw If the coordinates array is not set in any of \a meshes.
8134  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8135  *  \throw If \a meshes are of different space dimension.
8136  */
8137 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8138 {
8139   std::size_t sz=meshes.size();
8140   if(sz==0 || sz==1)
8141     return;
8142   std::vector< const DataArrayDouble * > coords(meshes.size());
8143   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8144   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8145     {
8146       if((*it))
8147         {
8148           (*it)->checkConnectivityFullyDefined();
8149           const DataArrayDouble *coo=(*it)->getCoords();
8150           if(coo)
8151             *it2=coo;
8152           else
8153             {
8154               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8155               oss << " has no coordinate array defined !";
8156               throw INTERP_KERNEL::Exception(oss.str().c_str());
8157             }
8158         }
8159       else
8160         {
8161           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8162           oss << " is null !";
8163           throw INTERP_KERNEL::Exception(oss.str().c_str());
8164         }
8165     }
8166   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8167   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8168   int offset=(*it)->getNumberOfNodes();
8169   (*it++)->setCoords(res);
8170   for(;it!=meshes.end();it++)
8171     {
8172       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8173       (*it)->setCoords(res);
8174       (*it)->shiftNodeNumbersInConn(offset);
8175       offset+=oldNumberOfNodes;
8176     }
8177 }
8178
8179 /*!
8180  * Merges nodes coincident with a given precision within all given meshes that share
8181  * the nodal connectivity array. The given meshes **can be of different** mesh
8182  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8183  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8184  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8185  *  \param [in,out] meshes - a vector of meshes to update.
8186  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8187  *  \throw If any of \a meshes is NULL.
8188  *  \throw If the \a meshes do not share the same node coordinates array.
8189  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8190  */
8191 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8192 {
8193   if(meshes.empty())
8194     return ;
8195   std::set<const DataArrayDouble *> s;
8196   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8197     {
8198       if(*it)
8199         s.insert((*it)->getCoords());
8200       else
8201         {
8202           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 !";
8203           throw INTERP_KERNEL::Exception(oss.str().c_str());
8204         }
8205     }
8206   if(s.size()!=1)
8207     {
8208       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 !";
8209       throw INTERP_KERNEL::Exception(oss.str().c_str());
8210     }
8211   const DataArrayDouble *coo=*(s.begin());
8212   if(!coo)
8213     return;
8214   //
8215   DataArrayInt *comm,*commI;
8216   coo->findCommonTuples(eps,-1,comm,commI);
8217   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8218   int oldNbOfNodes=coo->getNumberOfTuples();
8219   int newNbOfNodes;
8220   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8221   if(oldNbOfNodes==newNbOfNodes)
8222     return ;
8223   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8224   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8225     {
8226       (*it)->renumberNodesInConn(o2n->getConstPointer());
8227       (*it)->setCoords(newCoords);
8228     } 
8229 }
8230
8231 /*!
8232  * 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.
8233  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8234  * \param isQuad specifies the policy of connectivity.
8235  * @ret in/out parameter in which the result will be append
8236  */
8237 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8238 {
8239   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8240   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8241   ret.push_back(cm.getExtrudedType());
8242   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8243   switch(flatType)
8244   {
8245     case INTERP_KERNEL::NORM_POINT1:
8246       {
8247         ret.push_back(connBg[1]);
8248         ret.push_back(connBg[1]+nbOfNodesPerLev);
8249         break;
8250       }
8251     case INTERP_KERNEL::NORM_SEG2:
8252       {
8253         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8254         ret.insert(ret.end(),conn,conn+4);
8255         break;
8256       }
8257     case INTERP_KERNEL::NORM_SEG3:
8258       {
8259         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8260         ret.insert(ret.end(),conn,conn+8);
8261         break;
8262       }
8263     case INTERP_KERNEL::NORM_QUAD4:
8264       {
8265         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8266         ret.insert(ret.end(),conn,conn+8);
8267         break;
8268       }
8269     case INTERP_KERNEL::NORM_TRI3:
8270       {
8271         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8272         ret.insert(ret.end(),conn,conn+6);
8273         break;
8274       }
8275     case INTERP_KERNEL::NORM_TRI6:
8276       {
8277         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,
8278           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8279         ret.insert(ret.end(),conn,conn+15);
8280         break;
8281       }
8282     case INTERP_KERNEL::NORM_QUAD8:
8283       {
8284         int conn[20]={
8285           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8286           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8287           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8288         };
8289         ret.insert(ret.end(),conn,conn+20);
8290         break;
8291       }
8292     case INTERP_KERNEL::NORM_POLYGON:
8293       {
8294         std::back_insert_iterator< std::vector<int> > ii(ret);
8295         std::copy(connBg+1,connEnd,ii);
8296         *ii++=-1;
8297         std::reverse_iterator<const int *> rConnBg(connEnd);
8298         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8299         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8300         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8301         for(std::size_t i=0;i<nbOfRadFaces;i++)
8302           {
8303             *ii++=-1;
8304             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8305             std::copy(conn,conn+4,ii);
8306           }
8307         break;
8308       }
8309     default:
8310       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8311   }
8312 }
8313
8314 /*!
8315  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8316  */
8317 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8318 {
8319   std::size_t i, ip1;
8320   double v[3]={0.,0.,0.};
8321   std::size_t sz=std::distance(begin,end);
8322   if(isQuadratic)
8323     sz/=2;
8324   for(i=0;i<sz;i++)
8325     {
8326       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];
8327       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8328       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8329     }
8330   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8331
8332   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8333   // SEG3 forming a circle):
8334   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8335     {
8336       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8337       for(std::size_t j=0;j<sz;j++)
8338         {
8339           if (j%2)  // current point i is quadratic, next point i+1 is standard
8340             {
8341               i = sz+j;
8342               ip1 = (j+1)%sz; // ip1 = "i+1"
8343             }
8344           else      // current point i is standard, next point i+1 is quadratic
8345             {
8346               i = j;
8347               ip1 = j+sz;
8348             }
8349           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8350           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8351           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8352         }
8353       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8354     }
8355   return (ret>0.);
8356 }
8357
8358 /*!
8359  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8360  */
8361 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8362 {
8363   std::vector<std::pair<int,int> > edges;
8364   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8365   const int *bgFace=begin;
8366   for(std::size_t i=0;i<nbOfFaces;i++)
8367     {
8368       const int *endFace=std::find(bgFace+1,end,-1);
8369       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8370       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8371         {
8372           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8373           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8374             return false;
8375           edges.push_back(p1);
8376         }
8377       bgFace=endFace+1;
8378     }
8379   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8380 }
8381
8382 /*!
8383  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8384  */
8385 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8386 {
8387   double vec0[3],vec1[3];
8388   std::size_t sz=std::distance(begin,end);
8389   if(sz%2!=0)
8390     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8391   int nbOfNodes=(int)sz/2;
8392   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8393   const double *pt0=coords+3*begin[0];
8394   const double *pt1=coords+3*begin[nbOfNodes];
8395   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8396   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8397 }
8398
8399 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8400 {
8401   std::size_t sz=std::distance(begin,end);
8402   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8403   std::size_t nbOfNodes(sz/2);
8404   std::copy(begin,end,(int *)tmp);
8405   for(std::size_t j=1;j<nbOfNodes;j++)
8406     {
8407       begin[j]=tmp[nbOfNodes-j];
8408       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8409     }
8410 }
8411
8412 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8413 {
8414   std::size_t sz=std::distance(begin,end);
8415   if(sz!=4)
8416     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8417   double vec0[3],vec1[3];
8418   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8419   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]; 
8420   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;
8421 }
8422
8423 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8424 {
8425   std::size_t sz=std::distance(begin,end);
8426   if(sz!=5)
8427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8428   double vec0[3];
8429   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8430   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8431   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8432 }
8433
8434 /*!
8435  * 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 ) 
8436  * 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
8437  * a 2D space.
8438  *
8439  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8440  * \param [in] coords the coordinates with nb of components exactly equal to 3
8441  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8442  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8443  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8444  */
8445 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8446 {
8447   int nbFaces=std::count(begin+1,end,-1)+1;
8448   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8449   double *vPtr=v->getPointer();
8450   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8451   double *pPtr=p->getPointer();
8452   const int *stFaceConn=begin+1;
8453   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8454     {
8455       const int *endFaceConn=std::find(stFaceConn,end,-1);
8456       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8457       stFaceConn=endFaceConn+1;
8458     }
8459   pPtr=p->getPointer(); vPtr=v->getPointer();
8460   DataArrayInt *comm1=0,*commI1=0;
8461   v->findCommonTuples(eps,-1,comm1,commI1);
8462   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8463   const int *comm1Ptr=comm1->getConstPointer();
8464   const int *commI1Ptr=commI1->getConstPointer();
8465   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8466   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8467   //
8468   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8469   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8470   mm->finishInsertingCells();
8471   //
8472   for(int i=0;i<nbOfGrps1;i++)
8473     {
8474       int vecId=comm1Ptr[commI1Ptr[i]];
8475       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8476       DataArrayInt *comm2=0,*commI2=0;
8477       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8478       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8479       const int *comm2Ptr=comm2->getConstPointer();
8480       const int *commI2Ptr=commI2->getConstPointer();
8481       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8482       for(int j=0;j<nbOfGrps2;j++)
8483         {
8484           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8485             {
8486               res->insertAtTheEnd(begin,end);
8487               res->pushBackSilent(-1);
8488             }
8489           else
8490             {
8491               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8492               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8493               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8494               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8495               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8496               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8497               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8498               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8499               const int *idsNodePtr=idsNode->getConstPointer();
8500               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];
8501               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8502               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8503               if(std::abs(norm)>eps)
8504                 {
8505                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8506                   mm3->rotate(center,vec,angle);
8507                 }
8508               mm3->changeSpaceDimension(2);
8509               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8510               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8511               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8512               int nbOfCells=mm4->getNumberOfCells();
8513               for(int k=0;k<nbOfCells;k++)
8514                 {
8515                   int l=0;
8516                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8517                     res->pushBackSilent(idsNodePtr[*work]);
8518                   res->pushBackSilent(-1);
8519                 }
8520             }
8521         }
8522     }
8523   res->popBackSilent();
8524 }
8525
8526 /*!
8527  * 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
8528  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8529  * 
8530  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8531  * \param [in] coords coordinates expected to have 3 components.
8532  * \param [in] begin start of the nodal connectivity of the face.
8533  * \param [in] end end of the nodal connectivity (excluded) of the face.
8534  * \param [out] v the normalized vector of size 3
8535  * \param [out] p the pos of plane
8536  */
8537 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8538 {
8539   std::size_t nbPoints=std::distance(begin,end);
8540   if(nbPoints<3)
8541     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8542   double vec[3]={0.,0.,0.};
8543   std::size_t j=0;
8544   bool refFound=false;
8545   for(;j<nbPoints-1 && !refFound;j++)
8546     {
8547       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8548       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8549       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8550       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8551       if(norm>eps)
8552         {
8553           refFound=true;
8554           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8555         }
8556     }
8557   for(std::size_t i=j;i<nbPoints-1;i++)
8558     {
8559       double curVec[3];
8560       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8561       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8562       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8563       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8564       if(norm<eps)
8565         continue;
8566       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8567       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];
8568       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8569       if(norm>eps)
8570         {
8571           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8572           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8573           return ;
8574         }
8575     }
8576   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8577 }
8578
8579 /*!
8580  * This method tries to obtain a well oriented polyhedron.
8581  * If the algorithm fails, an exception will be thrown.
8582  */
8583 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8584 {
8585   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8586   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8587   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8588   isPerm[0]=true;
8589   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8590   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8591   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8592   //
8593   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8594     {
8595       bgFace=begin;
8596       std::size_t smthChanged=0;
8597       for(std::size_t i=0;i<nbOfFaces;i++)
8598         {
8599           endFace=std::find(bgFace+1,end,-1);
8600           nbOfEdgesInFace=std::distance(bgFace,endFace);
8601           if(!isPerm[i])
8602             {
8603               bool b;
8604               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8605                 {
8606                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8607                   std::pair<int,int> p2(p1.second,p1.first);
8608                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8609                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8610                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8611                 }
8612               if(isPerm[i])
8613                 { 
8614                   if(!b)
8615                     std::reverse(bgFace+1,endFace);
8616                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8617                     {
8618                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8619                       std::pair<int,int> p2(p1.second,p1.first);
8620                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8621                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8622                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8623                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8624                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8625                       if(it!=edgesOK.end())
8626                         {
8627                           edgesOK.erase(it);
8628                           edgesFinished.push_back(p1);
8629                         }
8630                       else
8631                         edgesOK.push_back(p1);
8632                     }
8633                 }
8634             }
8635           bgFace=endFace+1;
8636         }
8637       if(smthChanged==0)
8638         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8639     }
8640   if(!edgesOK.empty())
8641     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8642   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8643     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8644       bgFace=begin;
8645       for(std::size_t i=0;i<nbOfFaces;i++)
8646         {
8647           endFace=std::find(bgFace+1,end,-1);
8648           std::reverse(bgFace+1,endFace);
8649           bgFace=endFace+1;
8650         }
8651     }
8652 }
8653
8654 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8655 {
8656   int nbOfNodesExpected(skin->getNumberOfNodes());
8657   const int *n2oPtr(n2o->getConstPointer());
8658   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8659   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8660   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8661   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8662   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8663   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8664   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8665   if(nbOfNodesExpected<1)
8666     return ret.retn();
8667   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8668   *work++=n2oPtr[prevNode];
8669   for(int i=1;i<nbOfNodesExpected;i++)
8670     {
8671       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8672         {
8673           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8674           conn.erase(prevNode);
8675           if(conn.size()==1)
8676             {
8677               int curNode(*(conn.begin()));
8678               *work++=n2oPtr[curNode];
8679               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8680               shar.erase(prevCell);
8681               if(shar.size()==1)
8682                 {
8683                   prevCell=*(shar.begin());
8684                   prevNode=curNode;
8685                 }
8686               else
8687                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8688             }
8689           else
8690             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8691         }
8692       else
8693         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8694     }
8695   return ret.retn();
8696 }
8697
8698 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8699 {
8700   int nbOfNodesExpected(skin->getNumberOfNodes());
8701   int nbOfTurn(nbOfNodesExpected/2);
8702   const int *n2oPtr(n2o->getConstPointer());
8703   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8704   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8705   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8706   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8707   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8708   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8709   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8710   if(nbOfNodesExpected<1)
8711     return ret.retn();
8712   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8713   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8714   for(int i=1;i<nbOfTurn;i++)
8715     {
8716       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8717         {
8718           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8719           conn.erase(prevNode);
8720           if(conn.size()==1)
8721             {
8722               int curNode(*(conn.begin()));
8723               *work=n2oPtr[curNode];
8724               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8725               shar.erase(prevCell);
8726               if(shar.size()==1)
8727                 {
8728                   int curCell(*(shar.begin()));
8729                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8730                   prevCell=curCell;
8731                   prevNode=curNode;
8732                   work++;
8733                 }
8734               else
8735                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8736             }
8737           else
8738             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8739         }
8740       else
8741         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8742     }
8743   return ret.retn();
8744 }
8745
8746 /*!
8747  * This method makes the assumption spacedimension == meshdimension == 2.
8748  * This method works only for linear cells.
8749  * 
8750  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8751  */
8752 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8753 {
8754   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8755     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8756   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8757   int oldNbOfNodes(skin->getNumberOfNodes());
8758   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8759   int nbOfNodesExpected(skin->getNumberOfNodes());
8760   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8761   int nbCells(skin->getNumberOfCells());
8762   if(nbCells==nbOfNodesExpected)
8763     return buildUnionOf2DMeshLinear(skin,n2o);
8764   else if(2*nbCells==nbOfNodesExpected)
8765     return buildUnionOf2DMeshQuadratic(skin,n2o);
8766   else
8767     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8768 }
8769
8770 /*!
8771  * This method makes the assumption spacedimension == meshdimension == 3.
8772  * This method works only for linear cells.
8773  * 
8774  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8775  */
8776 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8777 {
8778   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8780   MCAuto<MEDCouplingUMesh> m=computeSkin();
8781   const int *conn=m->getNodalConnectivity()->getConstPointer();
8782   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8783   int nbOfCells=m->getNumberOfCells();
8784   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8785   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8786   if(nbOfCells<1)
8787     return ret.retn();
8788   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8789   for(int i=1;i<nbOfCells;i++)
8790     {
8791       *work++=-1;
8792       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8793     }
8794   return ret.retn();
8795 }
8796
8797 /*!
8798  * \brief Creates a graph of cell neighbors
8799  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8800  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8801  *  For example
8802  *  - index:  0 3 5 6 6
8803  *  - value:  1 2 3 2 3 3
8804  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8805  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8806  */
8807 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8808 {
8809   checkConnectivityFullyDefined();
8810
8811   int meshDim = this->getMeshDimension();
8812   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
8813   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
8814   this->getReverseNodalConnectivity(revConn,indexr);
8815   const int* indexr_ptr=indexr->getConstPointer();
8816   const int* revConn_ptr=revConn->getConstPointer();
8817
8818   const MEDCoupling::DataArrayInt* index;
8819   const MEDCoupling::DataArrayInt* conn;
8820   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8821   index=this->getNodalConnectivityIndex();
8822   int nbCells=this->getNumberOfCells();
8823   const int* index_ptr=index->getConstPointer();
8824   const int* conn_ptr=conn->getConstPointer();
8825
8826   //creating graph arcs (cell to cell relations)
8827   //arcs are stored in terms of (index,value) notation
8828   // 0 3 5 6 6
8829   // 1 2 3 2 3 3
8830   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8831   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8832
8833   //warning here one node have less than or equal effective number of cell with it
8834   //but cell could have more than effective nodes
8835   //because other equals nodes in other domain (with other global inode)
8836   std::vector <int> cell2cell_index(nbCells+1,0);
8837   std::vector <int> cell2cell;
8838   cell2cell.reserve(3*nbCells);
8839
8840   for (int icell=0; icell<nbCells;icell++)
8841     {
8842       std::map<int,int > counter;
8843       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8844         {
8845           int inode=conn_ptr[iconn];
8846           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8847             {
8848               int icell2=revConn_ptr[iconnr];
8849               std::map<int,int>::iterator iter=counter.find(icell2);
8850               if (iter!=counter.end()) (iter->second)++;
8851               else counter.insert(std::make_pair(icell2,1));
8852             }
8853         }
8854       for (std::map<int,int>::const_iterator iter=counter.begin();
8855            iter!=counter.end(); iter++)
8856         if (iter->second >= meshDim)
8857           {
8858             cell2cell_index[icell+1]++;
8859             cell2cell.push_back(iter->first);
8860           }
8861     }
8862   indexr->decrRef();
8863   revConn->decrRef();
8864   cell2cell_index[0]=0;
8865   for (int icell=0; icell<nbCells;icell++)
8866     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8867
8868   //filling up index and value to create skylinearray structure
8869   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8870   return array;
8871 }
8872
8873 /*!
8874  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8875  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8876  */
8877 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8878 {
8879   double *w=zipFrmt;
8880   if(spaceDim==3)
8881     for(int i=0;i<nbOfNodesInCell;i++)
8882       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8883   else if(spaceDim==2)
8884     {
8885       for(int i=0;i<nbOfNodesInCell;i++)
8886         {
8887           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8888           *w++=0.;
8889         }
8890     }
8891   else
8892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8893 }
8894
8895 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8896 {
8897   int nbOfCells=getNumberOfCells();
8898   if(nbOfCells<=0)
8899     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8900   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};
8901   ofs << "  <" << getVTKDataSetType() << ">\n";
8902   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8903   ofs << "      <PointData>\n" << pointData << std::endl;
8904   ofs << "      </PointData>\n";
8905   ofs << "      <CellData>\n" << cellData << std::endl;
8906   ofs << "      </CellData>\n";
8907   ofs << "      <Points>\n";
8908   if(getSpaceDimension()==3)
8909     _coords->writeVTK(ofs,8,"Points",byteData);
8910   else
8911     {
8912       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8913       coo->writeVTK(ofs,8,"Points",byteData);
8914     }
8915   ofs << "      </Points>\n";
8916   ofs << "      <Cells>\n";
8917   const int *cPtr=_nodal_connec->getConstPointer();
8918   const int *cIPtr=_nodal_connec_index->getConstPointer();
8919   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8920   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8921   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8922   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8923   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8924   int szFaceOffsets=0,szConn=0;
8925   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8926     {
8927       *w2=cPtr[cIPtr[i]];
8928       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8929         {
8930           *w1=-1;
8931           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8932           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8933         }
8934       else
8935         {
8936           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8937           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8938           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8939           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8940           w4=std::copy(c.begin(),c.end(),w4);
8941         }
8942     }
8943   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8944   types->writeVTK(ofs,8,"UInt8","types",byteData);
8945   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8946   if(szFaceOffsets!=0)
8947     {//presence of Polyhedra
8948       connectivity->reAlloc(szConn);
8949       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8950       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8951       w1=faces->getPointer();
8952       for(int i=0;i<nbOfCells;i++)
8953         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8954           {
8955             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8956             *w1++=nbFaces;
8957             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8958             for(int j=0;j<nbFaces;j++)
8959               {
8960                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8961                 *w1++=(int)std::distance(w6,w5);
8962                 w1=std::copy(w6,w5,w1);
8963                 w6=w5+1;
8964               }
8965           }
8966       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8967     }
8968   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8969   ofs << "      </Cells>\n";
8970   ofs << "    </Piece>\n";
8971   ofs << "  </" << getVTKDataSetType() << ">\n";
8972 }
8973
8974 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8975 {
8976   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8977   if(_mesh_dim==-2)
8978     { stream << " Not set !"; return ; }
8979   stream << " Mesh dimension : " << _mesh_dim << ".";
8980   if(_mesh_dim==-1)
8981     return ;
8982   if(!_coords)
8983     { stream << " No coordinates set !"; return ; }
8984   if(!_coords->isAllocated())
8985     { stream << " Coordinates set but not allocated !"; return ; }
8986   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8987   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8988   if(!_nodal_connec_index)
8989     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8990   if(!_nodal_connec_index->isAllocated())
8991     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8992   int lgth=_nodal_connec_index->getNumberOfTuples();
8993   int cpt=_nodal_connec_index->getNumberOfComponents();
8994   if(cpt!=1 || lgth<1)
8995     return ;
8996   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8997 }
8998
8999 std::string MEDCouplingUMesh::getVTKDataSetType() const
9000 {
9001   return std::string("UnstructuredGrid");
9002 }
9003
9004 std::string MEDCouplingUMesh::getVTKFileExtension() const
9005 {
9006   return std::string("vtu");
9007 }
9008
9009 /*!
9010  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9011  * returns a result mesh constituted by polygons.
9012  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9013  * all nodes from m2.
9014  * The meshes should be in 2D space. In
9015  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9016  * meshes.
9017  *  \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
9018  *                      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)
9019  *  \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
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] eps - precision used to detect coincident mesh entities.
9022  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9023  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9024  *         this array using decrRef() as it is no more needed.
9025  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9026  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9027  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9028  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9029  *         it is no more needed.  
9030  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9031  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9032  *         is no more needed.  
9033  *  \throw If the coordinates array is not set in any of the meshes.
9034  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9035  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9036  *
9037  *  \sa conformize2D, mergeNodes
9038  */
9039 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9040                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9041 {
9042   if(!m1 || !m2)
9043     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9044   m1->checkFullyDefined();
9045   m2->checkFullyDefined();
9046   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9047     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9048
9049   // Step 1: compute all edge intersections (new nodes)
9050   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9051   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9052   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9053   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9054   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9055                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9056                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9057   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9058   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9059   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9060
9061   // Step 2: re-order newly created nodes according to the ordering found in m2
9062   std::vector< std::vector<int> > intersectEdge2;
9063   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9064   subDiv2.clear(); dd5=0; dd6=0;
9065
9066   // Step 3:
9067   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9068   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9069   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9070                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9071
9072   // Step 4: Prepare final result:
9073   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9074   addCooDa->alloc((int)(addCoo.size())/2,2);
9075   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9076   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9077   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9078   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9079   std::vector<const DataArrayDouble *> coordss(4);
9080   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9081   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9082   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9083   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9084   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9085   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9086   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9087   ret->setConnectivity(conn,connI,true);
9088   ret->setCoords(coo);
9089   cellNb1=c1.retn(); cellNb2=c2.retn();
9090   return ret.retn();
9091 }
9092
9093 /// @cond INTERNAL
9094
9095 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9096 {
9097   if(candidates.empty())
9098     return false;
9099   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9100     {
9101       const std::vector<int>& pool(intersectEdge1[*it]);
9102       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9103       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9104         {
9105           retVal=*it+1;
9106           return true;
9107         }
9108       tmp[0]=stop; tmp[1]=start;
9109       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9110         {
9111           retVal=-*it-1;
9112           return true;
9113         }
9114     }
9115   return false;
9116 }
9117
9118 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,
9119                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9120 {
9121   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9122   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9123   int nCells(mesh1D->getNumberOfCells());
9124   if(nCells!=(int)intersectEdge2.size())
9125     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9126   const DataArrayDouble *coo2(mesh1D->getCoords());
9127   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9128   const double *coo2Ptr(coo2->begin());
9129   int offset1(coords1->getNumberOfTuples());
9130   int offset2(offset1+coo2->getNumberOfTuples());
9131   int offset3(offset2+addCoo.size()/2);
9132   std::vector<double> addCooQuad;
9133   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9134   int tmp[4],cicnt(0),kk(0);
9135   for(int i=0;i<nCells;i++)
9136     {
9137       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9138       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9139       const std::vector<int>& subEdges(intersectEdge2[i]);
9140       int nbSubEdge(subEdges.size()/2);
9141       for(int j=0;j<nbSubEdge;j++,kk++)
9142         {
9143           MCAuto<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
9144           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9145           INTERP_KERNEL::Edge *e2Ptr(e2);
9146           std::map<int,int>::const_iterator itm;
9147           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9148             {
9149               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9150               itm=mergedNodes.find(subEdges[2*j]);
9151               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9152               itm=mergedNodes.find(subEdges[2*j+1]);
9153               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9154               tmp[3]=offset3+(int)addCooQuad.size()/2;
9155               double tmp2[2];
9156               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9157               cicnt+=4;
9158               cOut->insertAtTheEnd(tmp,tmp+4);
9159               ciOut->pushBackSilent(cicnt);
9160             }
9161           else
9162             {
9163               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9164               itm=mergedNodes.find(subEdges[2*j]);
9165               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9166               itm=mergedNodes.find(subEdges[2*j+1]);
9167               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9168               cicnt+=3;
9169               cOut->insertAtTheEnd(tmp,tmp+3);
9170               ciOut->pushBackSilent(cicnt);
9171             }
9172           int tmp00;
9173           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9174             {
9175               idsInRetColinear->pushBackSilent(kk);
9176               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9177             }
9178         }
9179       e->decrRef();
9180     }
9181   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9182   ret->setConnectivity(cOut,ciOut,true);
9183   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9184   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9185   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9186   std::vector<const DataArrayDouble *> coordss(4);
9187   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9188   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9189   ret->setCoords(arr);
9190   return ret.retn();
9191 }
9192
9193 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9194 {
9195   std::vector<int> allEdges;
9196   for(const int *it2(descBg);it2!=descEnd;it2++)
9197     {
9198       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9199       if(*it2>0)
9200         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9201       else
9202         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9203     }
9204   std::size_t nb(allEdges.size());
9205   if(nb%2!=0)
9206     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9207   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9208   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9209   ret->setCoords(coords);
9210   ret->allocateCells(1);
9211   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9212   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9213     connOut[kk]=allEdges[2*kk];
9214   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9215   return ret.retn();
9216 }
9217
9218 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9219 {
9220   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9221   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9222   std::size_t ii(0);
9223   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9224   if(sz!=std::distance(descBg,descEnd))
9225     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9226   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9227   std::vector<int> allEdges,centers;
9228   const double *coordsPtr(coords->begin());
9229   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9230   int offset(coords->getNumberOfTuples());
9231   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9232     {
9233       INTERP_KERNEL::NormalizedCellType typeOfSon;
9234       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9235       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9236       if(*it2>0)
9237         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9238       else
9239         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9240       if(edge1.size()==2)
9241         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9242       else
9243         {//the current edge has been subsplit -> create corresponding centers.
9244           std::size_t nbOfCentersToAppend(edge1.size()/2);
9245           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9246           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9247           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9248           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9249             {
9250               double tmpp[2];
9251               const double *aa(coordsPtr+2*(*it3++));
9252               const double *bb(coordsPtr+2*(*it3++));
9253               ee->getMiddleOfPoints(aa,bb,tmpp);
9254               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9255               centers.push_back(offset+k);
9256             }
9257         }
9258     }
9259   std::size_t nb(allEdges.size());
9260   if(nb%2!=0)
9261     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9262   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9263   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9264   if(addCoo->empty())
9265     ret->setCoords(coords);
9266   else
9267     {
9268       addCoo->rearrange(2);
9269       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9270       ret->setCoords(addCoo);
9271     }
9272   ret->allocateCells(1);
9273   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9274   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9275     connOut[kk]=allEdges[2*kk];
9276   connOut.insert(connOut.end(),centers.begin(),centers.end());
9277   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9278   return ret.retn();
9279 }
9280
9281 /*!
9282  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9283  * of those edges.
9284  *
9285  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9286  */
9287 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9288 {
9289   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9290   if(!cm.isQuadratic())
9291     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9292   else
9293     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9294 }
9295
9296 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9297 {
9298   bool isQuad(false);
9299   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9300     {
9301       const INTERP_KERNEL::Edge *ee(*it);
9302       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9303         isQuad=true;
9304     }
9305   if(!isQuad)
9306     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9307   else
9308     {
9309       const double *coo(mesh2D->getCoords()->begin());
9310       std::size_t sz(conn.size());
9311       std::vector<double> addCoo;
9312       std::vector<int> conn2(conn);
9313       int offset(mesh2D->getNumberOfNodes());
9314       for(std::size_t i=0;i<sz;i++)
9315         {
9316           double tmp[2];
9317           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9318           addCoo.insert(addCoo.end(),tmp,tmp+2);
9319           conn2.push_back(offset+(int)i);
9320         }
9321       mesh2D->getCoords()->rearrange(1);
9322       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9323       mesh2D->getCoords()->rearrange(2);
9324       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9325     }
9326 }
9327
9328 /*!
9329  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9330  *
9331  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9332  * a set of edges defined in \a splitMesh1D.
9333  */
9334 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9335                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9336 {
9337   std::size_t nb(edge1Bis.size()/2);
9338   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9339   int iEnd(splitMesh1D->getNumberOfCells());
9340   if(iEnd==0)
9341     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9342   std::size_t ii,jj;
9343   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9344   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9345   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9346   //
9347   if(jj==nb)
9348     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9349       out0.resize(1); out1.resize(1);
9350       std::vector<int>& connOut(out0[0]);
9351       connOut.resize(nbOfEdgesOf2DCellSplit);
9352       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9353       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9354       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9355         {
9356           connOut[kk]=edge1Bis[2*kk];
9357           edgesPtr[kk]=edge1BisPtr[2*kk];
9358         }
9359     }
9360   else
9361     {
9362       // [i,iEnd[ contains the
9363       out0.resize(2); out1.resize(2);
9364       std::vector<int>& connOutLeft(out0[0]);
9365       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9366       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9367       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9368       for(std::size_t k=ii;k<jj+1;k++)
9369         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9370       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9371       for(int ik=0;ik<iEnd;ik++)
9372         {
9373           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9374           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9375           ees[ik]=ee;
9376         }
9377       for(int ik=iEnd-1;ik>=0;ik--)
9378         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9379       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9380         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9381       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9382       for(int ik=0;ik<iEnd;ik++)
9383         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9384       eright.insert(eright.end(),ees.begin(),ees.end());
9385     }
9386 }
9387
9388 /// @endcond
9389
9390 /// @cond INTERNAL
9391
9392 struct CellInfo
9393 {
9394 public:
9395   CellInfo() { }
9396   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9397 public:
9398   std::vector<int> _edges;
9399   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9400 };
9401
9402 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9403 {
9404   std::size_t nbe(edges.size());
9405   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9406   for(std::size_t i=0;i<nbe;i++)
9407     {
9408       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9409       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9410     }
9411   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9412   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9413   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9414 }
9415
9416 class EdgeInfo
9417 {
9418 public:
9419   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9420   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9421   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9422   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9423   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9424 private:
9425   int _istart;
9426   int _iend;
9427   MCAuto<MEDCouplingUMesh> _mesh;
9428   MCAuto<INTERP_KERNEL::Edge> _edge;
9429   int _left;
9430   int _right;
9431 };
9432
9433 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9434 {
9435   const MEDCouplingUMesh *mesh(_mesh);
9436   if(mesh)
9437     return ;
9438   if(_right<pos)
9439     return ;
9440   if(_left>pos)
9441     { _left++; _right++; return ; }
9442   if(_right==pos)
9443     {
9444       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9445       if((isLeft && isRight) || (!isLeft && !isRight))
9446         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9447       if(isLeft)
9448         return ;
9449       if(isRight)
9450         {
9451           _right++;
9452           return ;
9453         }
9454     }
9455   if(_left==pos)
9456     {
9457       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9458       if((isLeft && isRight) || (!isLeft && !isRight))
9459         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9460       if(isLeft)
9461         {
9462           _right++;
9463           return ;
9464         }
9465       if(isRight)
9466         {
9467           _left++;
9468           _right++;
9469           return ;
9470         }
9471     }
9472 }
9473
9474 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9475 {
9476   const MEDCouplingUMesh *mesh(_mesh);
9477   if(!mesh)
9478     {
9479       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9480     }
9481   else
9482     {// not fully splitting cell case
9483       if(mesh2D->getNumberOfCells()==1)
9484         {//little optimization. 1 cell no need to find in which cell mesh is !
9485           neighbors[0]=offset; neighbors[1]=offset;
9486           return;
9487         }
9488       else
9489         {
9490           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9491           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9492           if(cellId==-1)
9493             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9494           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9495         }
9496     }
9497 }
9498
9499 class VectorOfCellInfo
9500 {
9501 public:
9502   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9503   std::size_t size() const { return _pool.size(); }
9504   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9505   void setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs);
9506   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9507   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9508   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9509   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9510 private:
9511   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9512   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9513   const CellInfo& get(int pos) const;
9514   CellInfo& get(int pos);
9515 private:
9516   std::vector<CellInfo> _pool;
9517   MCAuto<MEDCouplingUMesh> _ze_mesh;
9518   std::vector<EdgeInfo> _edge_info;
9519 };
9520
9521 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9522 {
9523   _pool[0]._edges=edges;
9524   _pool[0]._edges_ptr=edgesPtr;
9525 }
9526
9527 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9528 {
9529   if(_pool.empty())
9530     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9531   if(_pool.size()==1)
9532     return 0;
9533   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9534   if(!zeMesh)
9535     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9536   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9537   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9538 }
9539
9540 void VectorOfCellInfo::setMeshAt(int pos, const MCAuto<MEDCouplingUMesh>& mesh, int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& edgePtrs)
9541 {
9542   get(pos);//to check pos
9543   bool isFast(pos==0 && _pool.size()==1);
9544   std::size_t sz(edges.size());
9545   // dealing with edges
9546   if(sz==1)
9547     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9548   else
9549     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9550   //
9551   std::vector<CellInfo> pool(_pool.size()-1+sz);
9552   for(int i=0;i<pos;i++)
9553     pool[i]=_pool[i];
9554   for(std::size_t j=0;j<sz;j++)
9555     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9556   for(int i=pos+1;i<(int)_pool.size();i++)
9557     pool[i+sz-1]=_pool[i];
9558   _pool=pool;
9559   //
9560   if(sz==2)
9561     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9562   //
9563   if(isFast)
9564     {
9565       _ze_mesh=mesh;
9566       return ;
9567     }
9568   //
9569   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9570   if(pos>0)
9571     {
9572       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9573       ms.push_back(elt);
9574     }
9575   ms.push_back(mesh);
9576   if(pos<_ze_mesh->getNumberOfCells()-1)
9577   {
9578     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9579     ms.push_back(elt);
9580   }
9581   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9582   for(std::size_t j=0;j<ms2.size();j++)
9583     ms2[j]=ms[j];
9584   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9585 }
9586
9587 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9588 {
9589   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9590 }
9591
9592 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9593 {
9594   if(pos<0)
9595     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9596   int ret(0);
9597   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9598     {
9599       if((*it).isInMyRange(pos))
9600         return ret;
9601     }
9602   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9603 }
9604
9605 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9606 {
9607   get(pos);//to check;
9608   if(_edge_info.empty())
9609     return ;
9610   std::size_t sz(_edge_info.size()-1);
9611   for(std::size_t i=0;i<sz;i++)
9612     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9613 }
9614
9615 const CellInfo& VectorOfCellInfo::get(int pos) const
9616 {
9617   if(pos<0 || pos>=(int)_pool.size())
9618     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9619   return _pool[pos];
9620 }
9621
9622 CellInfo& VectorOfCellInfo::get(int pos)
9623 {
9624   if(pos<0 || pos>=(int)_pool.size())
9625     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9626   return _pool[pos];
9627 }
9628
9629 /*!
9630  * Given :
9631  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9632  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9633  *
9634  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9635  *
9636  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9637  *
9638  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9639  */
9640 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9641                                          MCAuto<DataArrayInt>& idsLeftRight)
9642 {
9643   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9644   if(nbCellsInSplitMesh1D==0)
9645     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9646   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9647   std::size_t nb(allEdges.size()),jj;
9648   if(nb%2!=0)
9649     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9650   std::vector<int> edge1Bis(nb*2);
9651   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9652   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9653   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9654   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9655   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9656   //
9657   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9658   int *idsLeftRightPtr(idsLeftRight->getPointer());
9659   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9660   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9661     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9662       int iEnd(iStart);
9663       for(;iEnd<nbCellsInSplitMesh1D;)
9664         {
9665           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9666           if(jj!=nb)
9667             break;
9668           else
9669             iEnd++;
9670         }
9671       if(iEnd<nbCellsInSplitMesh1D)
9672         iEnd++;
9673       //
9674       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9675       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9676       //
9677       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9678       retTmp->setCoords(splitMesh1D->getCoords());
9679       retTmp->allocateCells();
9680
9681       std::vector< std::vector<int> > out0;
9682       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9683
9684       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9685       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9686         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9687       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9688       //
9689       iStart=iEnd;
9690     }
9691   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9692     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9693   return pool.getZeMesh().retn();
9694 }
9695
9696 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9697                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9698                                      MCAuto<DataArrayInt>& idsLeftRight)
9699 {
9700   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9701   //
9702   std::vector<int> allEdges;
9703   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9704   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9705     {
9706       int edgeId(std::abs(*it)-1);
9707       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9708       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9709       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9710       if(*it>0)
9711         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9712       else
9713         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9714       std::size_t sz(edge1.size());
9715       for(std::size_t cnt=0;cnt<sz;cnt++)
9716         allEdgesPtr.push_back(ee);
9717     }
9718   //
9719   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9720 }
9721
9722 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9723 {
9724   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9725     {//easy case comparison not
9726       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9727     }
9728   else if(typ1.isQuadratic() && typ2.isQuadratic())
9729     {
9730       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9731       if(!status0)
9732         return false;
9733       if(conn1[2]==conn2[2])
9734         return true;
9735       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9736       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9737       return dist<eps;
9738     }
9739   else
9740     {//only one is quadratic
9741       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9742       if(!status0)
9743         return false;
9744       const double *a(0),*bb(0),*be(0);
9745       if(typ1.isQuadratic())
9746         {
9747           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9748         }
9749       else
9750         {
9751           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9752         }
9753       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9754       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9755       return dist<eps;
9756     }
9757 }
9758
9759 /*!
9760  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9761  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9762  *
9763  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9764  */
9765 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9766 {
9767   if(candidatesIn2DEnd==candidatesIn2DBg)
9768     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9769   const double *coo(mesh2DSplit->getCoords()->begin());
9770   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9771     return *candidatesIn2DBg;
9772   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9773   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9774   if(cellIdInMesh1DSplitRelative<0)
9775     cur1D->changeOrientationOfCells();
9776   const int *c1D(cur1D->getNodalConnectivity()->begin());
9777   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9778   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9779     {
9780       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9781       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9782       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9783       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9784       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9785       for(unsigned it2=0;it2<sz;it2++)
9786         {
9787           INTERP_KERNEL::NormalizedCellType typeOfSon;
9788           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9789           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9790           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9791             return *it;
9792         }
9793     }
9794   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9795 }
9796
9797 /// @endcond
9798
9799 /*!
9800  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9801  * 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
9802  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9803  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9804  *
9805  * \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
9806  *                      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)
9807  * \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
9808  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9809  * \param [in] eps - precision used to perform intersections and localization operations.
9810  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9811  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9812  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9813  *                               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.
9814  * \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
9815  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9816  *                               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.
9817  *
9818  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9819  */
9820 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9821 {
9822   if(!mesh2D || !mesh1D)
9823     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9824   mesh2D->checkFullyDefined();
9825   mesh1D->checkFullyDefined();
9826   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9827   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9828     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9829   // Step 1: compute all edge intersections (new nodes)
9830   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9831   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9832   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9833   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9834   //
9835   // Build desc connectivity
9836   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9837   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9838   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9839   std::map<int,int> mergedNodes;
9840   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9841   // use mergeNodes to fix intersectEdge1
9842   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9843     {
9844       std::size_t n((*it0).size()/2);
9845       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9846       std::map<int,int>::const_iterator it1;
9847       it1=mergedNodes.find(eltStart);
9848       if(it1!=mergedNodes.end())
9849         (*it0)[0]=(*it1).second;
9850       it1=mergedNodes.find(eltEnd);
9851       if(it1!=mergedNodes.end())
9852         (*it0)[2*n-1]=(*it1).second;
9853     }
9854   //
9855   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9856   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9857   // Step 2: re-order newly created nodes according to the ordering found in m2
9858   std::vector< std::vector<int> > intersectEdge2;
9859   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9860   subDiv2.clear();
9861   // Step 3: compute splitMesh1D
9862   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9863   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9864   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9865       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9866   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9867   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9868   // deal with cells in mesh2D that are not cut but only some of their edges are
9869   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
9870   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9871   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9872   MCAuto<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9873   if(!idsInDesc2DToBeRefined->empty())
9874     {
9875       DataArrayInt *out0(0),*outi0(0);
9876       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9877       MCAuto<DataArrayInt> outi0s(outi0);
9878       out0s=out0;
9879       out0s=out0s->buildUnique();
9880       out0s->sort(true);
9881     }
9882   //
9883   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9884   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
9885   MCAuto<DataArrayInt> elts,eltsIndex;
9886   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9887   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9888   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
9889   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9890     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9891   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
9892   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9893   if((DataArrayInt *)out0s)
9894     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9895   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
9896   // OK all is ready to insert in ret2 mesh
9897   if(!untouchedCells->empty())
9898     {// the most easy part, cells in mesh2D not impacted at all
9899       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9900       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9901       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9902     }
9903   if((DataArrayInt *)out0s)
9904     {// here dealing with cells in out0s but not in cellsToBeModified
9905       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9906       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9907       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9908         {
9909           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9910           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9911         }
9912       int offset(ret2->getNumberOfTuples());
9913       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9914       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9915       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9916       int kk(0),*ret3ptr(partOfRet3->getPointer());
9917       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9918         {
9919           int faceId(std::abs(*it)-1);
9920           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9921             {
9922               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
9923               if(tmp!=-1)
9924                 {
9925                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9926                     ret3ptr[2*kk]=tmp+offset;
9927                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9928                     ret3ptr[2*kk+1]=tmp+offset;
9929                 }
9930               else
9931                 {//the current edge is shared by a 2D cell that will be split just after
9932                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9933                     ret3ptr[2*kk]=-(*it2+1);
9934                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9935                     ret3ptr[2*kk+1]=-(*it2+1);
9936                 }
9937             }
9938         }
9939       m1Desc->setCoords(ret1->getCoords());
9940       ret1NonCol->setCoords(ret1->getCoords());
9941       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9942       if(!outMesh2DSplit.empty())
9943         {
9944           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9945           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9946             (*itt)->setCoords(da);
9947         }
9948     }
9949   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9950   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9951     {
9952       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
9953       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9954       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9955       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9956       MCAuto<DataArrayInt> partOfRet3;
9957       MCAuto<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9958       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9959       outMesh2DSplit.push_back(splitOfOneCell);
9960       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9961         ret2->pushBackSilent(*it);
9962     }
9963   //
9964   std::size_t nbOfMeshes(outMesh2DSplit.size());
9965   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9966   for(std::size_t i=0;i<nbOfMeshes;i++)
9967     tmp[i]=outMesh2DSplit[i];
9968   //
9969   ret1->getCoords()->setInfoOnComponents(compNames);
9970   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9971   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9972   ret3->rearrange(1);
9973   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
9974   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9975     {
9976       int old2DCellId(-ret3->getIJ(*it,0)-1);
9977       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
9978       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
9979     }
9980   ret3->changeValue(std::numeric_limits<int>::max(),-1);
9981   ret3->rearrange(2);
9982   //
9983   splitMesh1D=ret1.retn();
9984   splitMesh2D=ret2D.retn();
9985   cellIdInMesh2D=ret2.retn();
9986   cellIdInMesh1D=ret3.retn();
9987 }
9988
9989 /**
9990  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9991  * (newly created) nodes corresponding to the edge intersections.
9992  * Output params:
9993  * @param[out] cr, crI connectivity of the resulting mesh
9994  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9995  * TODO: describe input parameters
9996  */
9997 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9998                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9999                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
10000                                                          const std::vector<double>& addCoords,
10001                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10002 {
10003   static const int SPACEDIM=2;
10004   const double *coo1(m1->getCoords()->getConstPointer());
10005   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
10006   int offset1(m1->getNumberOfNodes());
10007   const double *coo2(m2->getCoords()->getConstPointer());
10008   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
10009   int offset2(offset1+m2->getNumberOfNodes());
10010   int offset3(offset2+((int)addCoords.size())/2);
10011   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10012   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10013   // Here a BBTree on 2D-cells, not on segments:
10014   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10015   int ncell1(m1->getNumberOfCells());
10016   crI.push_back(0);
10017   for(int i=0;i<ncell1;i++)
10018     {
10019       std::vector<int> candidates2;
10020       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10021       std::map<INTERP_KERNEL::Node *,int> mapp;
10022       std::map<int,INTERP_KERNEL::Node *> mappRev;
10023       INTERP_KERNEL::QuadraticPolygon pol1;
10024       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10025       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10026       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10027       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10028       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10029       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10030           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10031       //
10032       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
10033       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10034       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10035       for(it1.first();!it1.finished();it1.next())
10036         edges1.insert(it1.current()->getPtr());
10037       //
10038       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10039       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10040       int ii=0;
10041       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10042         {
10043           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10044           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10045           // Complete mapping with elements coming from the current cell it2 in mesh2:
10046           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10047           // pol2 is the new QP in the final merged result.
10048           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10049               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10050         }
10051       ii=0;
10052       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10053         {
10054           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10055           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10056           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10057           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10058         }
10059       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10060       // by m2 but that we still want to keep in the final result.
10061       if(!edges1.empty())
10062         {
10063           try
10064           {
10065               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10066           }
10067           catch(INTERP_KERNEL::Exception& e)
10068           {
10069               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();
10070               throw INTERP_KERNEL::Exception(oss.str().c_str());
10071           }
10072         }
10073       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10074         (*it).second->decrRef();
10075     }
10076 }
10077
10078 /**
10079  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10080  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10081  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10082  * The caller is to deal with the resulting DataArrayInt.
10083  *  \throw If the coordinate array is not set.
10084  *  \throw If the nodal connectivity of the cells is not defined.
10085  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10086  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10087  *
10088  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10089  */
10090 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10091 {
10092   checkFullyDefined();
10093   if(getMeshDimension()!=1)
10094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10095
10096   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10097   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10098   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10099   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10100   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10101   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10102   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10103   const int * dsi(_dsi->getConstPointer());
10104   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10105   m_points=0;
10106   if (dsii->getNumberOfTuples())
10107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10108
10109   int nc(getNumberOfCells());
10110   MCAuto<DataArrayInt> result(DataArrayInt::New());
10111   result->alloc(nc,1);
10112
10113   // set of edges not used so far
10114   std::set<int> edgeSet;
10115   for (int i=0; i<nc; edgeSet.insert(i), i++);
10116
10117   int startSeg=0;
10118   int newIdx=0;
10119   // while we have points with only one neighbor segments
10120   do
10121     {
10122       std::list<int> linePiece;
10123       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10124       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10125         {
10126           // Fill the list forward (resp. backward) from the start segment:
10127           int activeSeg = startSeg;
10128           int prevPointId = -20;
10129           int ptId;
10130           while (!edgeSet.empty())
10131             {
10132               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10133                 {
10134                   if (direction==0)
10135                     linePiece.push_back(activeSeg);
10136                   else
10137                     linePiece.push_front(activeSeg);
10138                   edgeSet.erase(activeSeg);
10139                 }
10140
10141               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10142               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10143               if (dsi[ptId] == 1) // hitting the end of the line
10144                 break;
10145               prevPointId = ptId;
10146               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10147               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10148             }
10149         }
10150       // Done, save final piece into DA:
10151       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10152       newIdx += linePiece.size();
10153
10154       // identify next valid start segment (one which is not consumed)
10155       if(!edgeSet.empty())
10156         startSeg = *(edgeSet.begin());
10157     }
10158   while (!edgeSet.empty());
10159   return result.retn();
10160 }
10161
10162 /// @cond INTERNAL
10163
10164 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10165 {
10166   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10167   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10168   if(it==m.end())
10169     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10170   int v((*it).second);
10171   if(v==forbVal0 || v==forbVal1)
10172     return ;
10173   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10174     isect.push_back(v);
10175 }
10176
10177 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10178 {
10179   int sz(c.size());
10180   if(sz<=1)
10181     return false;
10182   bool presenceOfOn(false);
10183   for(int i=0;i<sz;i++)
10184     {
10185       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10186       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10187         continue ;
10188       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10189       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10190     }
10191   return presenceOfOn;
10192 }
10193
10194 /// @endcond
10195
10196 /**
10197  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10198  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10199  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10200  * a minimal creation of new nodes is wanted.
10201  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10202  * nodes if a SEG3 is split without information of middle.
10203  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10204  * avoid to have a non conform mesh.
10205  *
10206  * \return int - the number of new nodes created (in most of cases 0).
10207  * 
10208  * \throw If \a this is not coherent.
10209  * \throw If \a this has not spaceDim equal to 2.
10210  * \throw If \a this has not meshDim equal to 2.
10211  * \throw If some subcells needed to be split are orphan.
10212  * \sa MEDCouplingUMesh::conformize2D
10213  */
10214 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10215 {
10216   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10218   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10219   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10220     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10221   if(midOpt==0 && midOptI==0)
10222     {
10223       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10224       return 0;
10225     }
10226   else if(midOpt!=0 && midOptI!=0)
10227     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10228   else
10229     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10230 }
10231
10232 /*!
10233  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10234  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10235  * 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
10236  * 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).
10237  * 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.
10238  * 
10239  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10240  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10241  *
10242  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10243  * This method expects that all nodes in \a this are not closer than \a eps.
10244  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10245  * 
10246  * \param [in] eps the relative error to detect merged edges.
10247  * \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
10248  *                           that the user is expected to deal with.
10249  *
10250  * \throw If \a this is not coherent.
10251  * \throw If \a this has not spaceDim equal to 2.
10252  * \throw If \a this has not meshDim equal to 2.
10253  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10254  */
10255 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10256 {
10257   static const int SPACEDIM=2;
10258   checkConsistencyLight();
10259   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10261   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10262   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10263   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10264   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10265   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10266   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10267   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10268   std::vector<double> addCoo;
10269   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10270   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10271   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10272   for(int i=0;i<nDescCell;i++)
10273     {
10274       std::vector<int> candidates;
10275       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10276       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10277         if(*it>i)
10278           {
10279             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10280             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10281                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10282             INTERP_KERNEL::MergePoints merge;
10283             INTERP_KERNEL::QuadraticPolygon c1,c2;
10284             e1->intersectWith(e2,merge,c1,c2);
10285             e1->decrRef(); e2->decrRef();
10286             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10287               overlapEdge[i].push_back(*it);
10288             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10289               overlapEdge[*it].push_back(i);
10290           }
10291     }
10292   // splitting done. sort intersect point in intersectEdge.
10293   std::vector< std::vector<int> > middle(nDescCell);
10294   int nbOf2DCellsToBeSplit(0);
10295   bool middleNeedsToBeUsed(false);
10296   std::vector<bool> cells2DToTreat(nDescCell,false);
10297   for(int i=0;i<nDescCell;i++)
10298     {
10299       std::vector<int>& isect(intersectEdge[i]);
10300       int sz((int)isect.size());
10301       if(sz>1)
10302         {
10303           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10304           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10305           e->sortSubNodesAbs(coords,isect);
10306           e->decrRef();
10307         }
10308       if(sz!=0)
10309         {
10310           int idx0(rdi[i]),idx1(rdi[i+1]);
10311           if(idx1-idx0!=1)
10312             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10313           if(!cells2DToTreat[rd[idx0]])
10314             {
10315               cells2DToTreat[rd[idx0]]=true;
10316               nbOf2DCellsToBeSplit++;
10317             }
10318           // try to reuse at most eventual 'middle' of SEG3
10319           std::vector<int>& mid(middle[i]);
10320           mid.resize(sz+1,-1);
10321           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10322             {
10323               middleNeedsToBeUsed=true;
10324               const std::vector<int>& candidates(overlapEdge[i]);
10325               std::vector<int> trueCandidates;
10326               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10327                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10328                   trueCandidates.push_back(*itc);
10329               int stNode(c[ci[i]+1]),endNode(isect[0]);
10330               for(int j=0;j<sz+1;j++)
10331                 {
10332                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10333                     {
10334                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10335                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10336                         { mid[j]=*itc; break; }
10337                     }
10338                   stNode=endNode;
10339                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10340                 }
10341             }
10342         }
10343     }
10344   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10345   if(nbOf2DCellsToBeSplit==0)
10346     return ret.retn();
10347   //
10348   int *retPtr(ret->getPointer());
10349   for(int i=0;i<nCell;i++)
10350     if(cells2DToTreat[i])
10351       *retPtr++=i;
10352   //
10353   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10354   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10355   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10356   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10357   if(middleNeedsToBeUsed)
10358     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10359   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10360   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10361   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.
10362   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10363   {
10364     bool areNodesMerged; int newNbOfNodes;
10365     if(nbOfNodesCreated!=0)
10366       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10367   }
10368   return ret.retn();
10369 }
10370
10371 /*!
10372  * 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.
10373  * 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).
10374  * 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
10375  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10376  * 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
10377  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10378  *
10379  * 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
10380  * using new instance, idem for coordinates.
10381  *
10382  * 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.
10383  * 
10384  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10385  *
10386  * \throw If \a this is not coherent.
10387  * \throw If \a this has not spaceDim equal to 2.
10388  * \throw If \a this has not meshDim equal to 2.
10389  * 
10390  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10391  */
10392 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10393 {
10394   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10395   checkConsistencyLight();
10396   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10397     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10398   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10399   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10400   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10401   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10402   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10403   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10404   const double *coords(_coords->begin());
10405   int *newciptr(newci->getPointer());
10406   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10407     {
10408       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10409         ret->pushBackSilent(i);
10410       newciptr[1]=newc->getNumberOfTuples();
10411     }
10412   //
10413   if(ret->empty())
10414     return ret.retn();
10415   if(!appendedCoords->empty())
10416     {
10417       appendedCoords->rearrange(2);
10418       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10419       //non const part
10420       setCoords(newCoords);
10421     }
10422   //non const part
10423   setConnectivity(newc,newci,true);
10424   return ret.retn();
10425 }
10426
10427 /*!
10428  * \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.
10429  *                               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.
10430  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10431  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10432  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10433  * \param [out] addCoo - nodes to be append at the end
10434  * \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.
10435  */
10436 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10437                                          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)
10438 {
10439   static const int SPACEDIM=2;
10440   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10441   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10442   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10443   // Build BB tree of all edges in the tool mesh (second mesh)
10444   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10445   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10446   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10447   intersectEdge1.resize(nDescCell1);
10448   colinear2.resize(nDescCell2);
10449   subDiv2.resize(nDescCell2);
10450   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10451
10452   std::vector<int> candidates1(1);
10453   int offset1(m1Desc->getNumberOfNodes());
10454   int offset2(offset1+m2Desc->getNumberOfNodes());
10455   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10456     {
10457       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10458       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10459       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10460         {
10461           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10462           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10463           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10464           candidates1[0]=i;
10465           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10466           // 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
10467           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10468           std::set<INTERP_KERNEL::Node *> nodes;
10469           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10470           std::size_t szz(nodes.size());
10471           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10472           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10473           for(std::size_t iii=0;iii<szz;iii++,itt++)
10474             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10475           // end of protection
10476           // Performs egde cutting:
10477           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10478           delete pol2;
10479           delete pol1;
10480         }
10481       else
10482         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10483         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10484     }
10485 }
10486
10487 /*!
10488  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10489  * It builds the descending connectivity of the two meshes, and then using a binary tree
10490  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10491  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10492  */
10493 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10494                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10495                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10496                                                    std::vector<double>& addCoo,
10497                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10498 {
10499   // Build desc connectivity
10500   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10501   desc2=DataArrayInt::New();
10502   descIndx2=DataArrayInt::New();
10503   revDesc2=DataArrayInt::New();
10504   revDescIndx2=DataArrayInt::New();
10505   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10506   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10507   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10508   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10509   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10510   std::map<int,int> notUsedMap;
10511   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10512   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10513   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10514 }
10515
10516 /*!
10517  * This method performs the 2nd step of Partition of 2D mesh.
10518  * This method has 4 inputs :
10519  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10520  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10521  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10522  * 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'
10523  * Nodes end up lying consecutively on a cutted edge.
10524  * \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.
10525  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10526  * \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.
10527  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10528  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10529  */
10530 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10531                                            const std::vector<double>& addCoo,
10532                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10533 {
10534   int offset1=m1->getNumberOfNodes();
10535   int ncell=m2->getNumberOfCells();
10536   const int *c=m2->getNodalConnectivity()->getConstPointer();
10537   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10538   const double *coo=m2->getCoords()->getConstPointer();
10539   const double *cooBis=m1->getCoords()->getConstPointer();
10540   int offset2=offset1+m2->getNumberOfNodes();
10541   intersectEdge.resize(ncell);
10542   for(int i=0;i<ncell;i++,cI++)
10543     {
10544       const std::vector<int>& divs=subDiv[i];
10545       int nnode=cI[1]-cI[0]-1;
10546       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10547       std::map<INTERP_KERNEL::Node *, int> mapp22;
10548       for(int j=0;j<nnode;j++)
10549         {
10550           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10551           int nnid=c[(*cI)+j+1];
10552           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10553           mapp22[nn]=nnid+offset1;
10554         }
10555       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10556       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10557         ((*it).second.first)->decrRef();
10558       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10559       std::map<INTERP_KERNEL::Node *,int> mapp3;
10560       for(std::size_t j=0;j<divs.size();j++)
10561         {
10562           int id=divs[j];
10563           INTERP_KERNEL::Node *tmp=0;
10564           if(id<offset1)
10565             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10566           else if(id<offset2)
10567             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10568           else
10569             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10570           addNodes[j]=tmp;
10571           mapp3[tmp]=id;
10572         }
10573       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10574       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10575         (*it)->decrRef();
10576       e->decrRef();
10577     }
10578 }
10579
10580 /*!
10581  * 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).
10582  * 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
10583  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10584  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10585  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10586  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10587  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10588  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10589  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10590  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10591  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10592  * \param [out] cut3DSuf input/output param.
10593  */
10594 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10595                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10596                                                    const int *desc, const int *descIndx, 
10597                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10598 {
10599   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10600   int nbOf3DSurfCell=(int)cut3DSurf.size();
10601   for(int i=0;i<nbOf3DSurfCell;i++)
10602     {
10603       std::vector<int> res;
10604       int offset=descIndx[i];
10605       int nbOfSeg=descIndx[i+1]-offset;
10606       for(int j=0;j<nbOfSeg;j++)
10607         {
10608           int edgeId=desc[offset+j];
10609           int status=cut3DCurve[edgeId];
10610           if(status!=-2)
10611             {
10612               if(status>-1)
10613                 res.push_back(status);
10614               else
10615                 {
10616                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10617                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10618                 }
10619             }
10620         }
10621       switch(res.size())
10622       {
10623         case 2:
10624           {
10625             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10626             break;
10627           }
10628         case 1:
10629         case 0:
10630           {
10631             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10632             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10633             if(res.size()==2)
10634               {
10635                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10636               }
10637             else
10638               {
10639                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10640               }
10641             break;
10642           }
10643         default:
10644           {// case when plane is on a multi colinear edge of a polyhedron
10645             if((int)res.size()==2*nbOfSeg)
10646               {
10647                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10648               }
10649             else
10650               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10651           }
10652       }
10653     }
10654 }
10655
10656 /*!
10657  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10658  * 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).
10659  * 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
10660  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10661  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10662  * \param desc is the descending connectivity 3D->3DSurf
10663  * \param descIndx is the descending connectivity index 3D->3DSurf
10664  */
10665 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10666                                                   const int *desc, const int *descIndx,
10667                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10668 {
10669   checkFullyDefined();
10670   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10672   const int *nodal3D=_nodal_connec->getConstPointer();
10673   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10674   int nbOfCells=getNumberOfCells();
10675   for(int i=0;i<nbOfCells;i++)
10676     {
10677       std::map<int, std::set<int> > m;
10678       int offset=descIndx[i];
10679       int nbOfFaces=descIndx[i+1]-offset;
10680       int start=-1;
10681       int end=-1;
10682       for(int j=0;j<nbOfFaces;j++)
10683         {
10684           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10685           if(p.first!=-1 && p.second!=-1)
10686             {
10687               if(p.first!=-2)
10688                 {
10689                   start=p.first; end=p.second;
10690                   m[p.first].insert(p.second);
10691                   m[p.second].insert(p.first);
10692                 }
10693               else
10694                 {
10695                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10696                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10697                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10698                   INTERP_KERNEL::NormalizedCellType cmsId;
10699                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10700                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10701                   for(unsigned k=0;k<nbOfNodesSon;k++)
10702                     {
10703                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10704                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10705                     }
10706                 }
10707             }
10708         }
10709       if(m.empty())
10710         continue;
10711       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10712       int prev=end;
10713       while(end!=start)
10714         {
10715           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10716           const std::set<int>& s=(*it).second;
10717           std::set<int> s2; s2.insert(prev);
10718           std::set<int> s3;
10719           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10720           if(s3.size()==1)
10721             {
10722               int val=*s3.begin();
10723               conn.push_back(start);
10724               prev=start;
10725               start=val;
10726             }
10727           else
10728             start=end;
10729         }
10730       conn.push_back(end);
10731       if(conn.size()>3)
10732         {
10733           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10734           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10735           cellIds->pushBackSilent(i);
10736         }
10737     }
10738 }
10739
10740 /*!
10741  * 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
10742  * 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
10743  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10744  * 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
10745  * 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.
10746  * 
10747  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10748  */
10749 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10750 {
10751   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10752   if(sz>=4)
10753     {
10754       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10755       if(cm.getDimension()==2)
10756         {
10757           const int *node=nodalConnBg+1;
10758           int startNode=*node++;
10759           double refX=coords[2*startNode];
10760           for(;node!=nodalConnEnd;node++)
10761             {
10762               if(coords[2*(*node)]<refX)
10763                 {
10764                   startNode=*node;
10765                   refX=coords[2*startNode];
10766                 }
10767             }
10768           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10769           refX=1e300;
10770           double tmp1;
10771           double tmp2[2];
10772           double angle0=-M_PI/2;
10773           //
10774           int nextNode=-1;
10775           int prevNode=-1;
10776           double resRef;
10777           double angleNext=0.;
10778           while(nextNode!=startNode)
10779             {
10780               nextNode=-1;
10781               resRef=1e300;
10782               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10783                 {
10784                   if(*node!=tmpOut.back() && *node!=prevNode)
10785                     {
10786                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10787                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10788                       double res;
10789                       if(angleM<=angle0)
10790                         res=angle0-angleM;
10791                       else
10792                         res=angle0-angleM+2.*M_PI;
10793                       if(res<resRef)
10794                         {
10795                           nextNode=*node;
10796                           resRef=res;
10797                           angleNext=angleM;
10798                         }
10799                     }
10800                 }
10801               if(nextNode!=startNode)
10802                 {
10803                   angle0=angleNext-M_PI;
10804                   if(angle0<-M_PI)
10805                     angle0+=2*M_PI;
10806                   prevNode=tmpOut.back();
10807                   tmpOut.push_back(nextNode);
10808                 }
10809             }
10810           std::vector<int> tmp3(2*(sz-1));
10811           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10812           std::copy(nodalConnBg+1,nodalConnEnd,it);
10813           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10814             {
10815               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10816               return false;
10817             }
10818           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10819             {
10820               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10821               return false;
10822             }
10823           else
10824             {
10825               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10826               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10827               return true;
10828             }
10829         }
10830       else
10831         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10832     }
10833   else
10834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10835 }
10836
10837 /*!
10838  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10839  * 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.
10840  * 
10841  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10842  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10843  * \param [in,out] arr array in which the remove operation will be done.
10844  * \param [in,out] arrIndx array in the remove operation will modify
10845  * \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])
10846  * \return true if \b arr and \b arrIndx have been modified, false if not.
10847  */
10848 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10849 {
10850   if(!arrIndx || !arr)
10851     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10852   if(offsetForRemoval<0)
10853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10854   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10855   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10856   int *arrIPtr=arrIndx->getPointer();
10857   *arrIPtr++=0;
10858   int previousArrI=0;
10859   const int *arrPtr=arr->getConstPointer();
10860   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10861   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10862     {
10863       if(*arrIPtr-previousArrI>offsetForRemoval)
10864         {
10865           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10866             {
10867               if(s.find(*work)==s.end())
10868                 arrOut.push_back(*work);
10869             }
10870         }
10871       previousArrI=*arrIPtr;
10872       *arrIPtr=(int)arrOut.size();
10873     }
10874   if(arr->getNumberOfTuples()==(int)arrOut.size())
10875     return false;
10876   arr->alloc((int)arrOut.size(),1);
10877   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10878   return true;
10879 }
10880
10881 /*!
10882  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10883  * (\ref numbering-indirect).
10884  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10885  * The selection of extraction is done standardly in new2old format.
10886  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10887  *
10888  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10889  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10890  * \param [in] arrIn arr origin array from which the extraction will be done.
10891  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10892  * \param [out] arrOut the resulting array
10893  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10894  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
10895  */
10896 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10897                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10898 {
10899   if(!arrIn || !arrIndxIn)
10900     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10901   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10902   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10904   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10905   const int *arrInPtr=arrIn->getConstPointer();
10906   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10907   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10908   if(nbOfGrps<0)
10909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10910   int maxSizeOfArr=arrIn->getNumberOfTuples();
10911   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10912   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10913   arrIo->alloc((int)(sz+1),1);
10914   const int *idsIt=idsOfSelectBg;
10915   int *work=arrIo->getPointer();
10916   *work++=0;
10917   int lgth=0;
10918   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10919     {
10920       if(*idsIt>=0 && *idsIt<nbOfGrps)
10921         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10922       else
10923         {
10924           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10925           throw INTERP_KERNEL::Exception(oss.str().c_str());
10926         }
10927       if(lgth>=work[-1])
10928         *work=lgth;
10929       else
10930         {
10931           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10932           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10933           throw INTERP_KERNEL::Exception(oss.str().c_str());
10934         }
10935     }
10936   arro->alloc(lgth,1);
10937   work=arro->getPointer();
10938   idsIt=idsOfSelectBg;
10939   for(std::size_t i=0;i<sz;i++,idsIt++)
10940     {
10941       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10942         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10943       else
10944         {
10945           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10946           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10947           throw INTERP_KERNEL::Exception(oss.str().c_str());
10948         }
10949     }
10950   arrOut=arro.retn();
10951   arrIndexOut=arrIo.retn();
10952 }
10953
10954 /*!
10955  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10956  * (\ref numbering-indirect).
10957  * 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 ).
10958  * The selection of extraction is done standardly in new2old format.
10959  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10960  *
10961  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10962  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10963  * \param [in] idsOfSelectStep
10964  * \param [in] arrIn arr origin array from which the extraction will be done.
10965  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10966  * \param [out] arrOut the resulting array
10967  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10968  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10969  */
10970 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10971                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10972 {
10973   if(!arrIn || !arrIndxIn)
10974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
10975   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10976   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
10978   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
10979   const int *arrInPtr=arrIn->getConstPointer();
10980   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10981   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10982   if(nbOfGrps<0)
10983     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10984   int maxSizeOfArr=arrIn->getNumberOfTuples();
10985   MCAuto<DataArrayInt> arro=DataArrayInt::New();
10986   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
10987   arrIo->alloc((int)(sz+1),1);
10988   int idsIt=idsOfSelectStart;
10989   int *work=arrIo->getPointer();
10990   *work++=0;
10991   int lgth=0;
10992   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10993     {
10994       if(idsIt>=0 && idsIt<nbOfGrps)
10995         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10996       else
10997         {
10998           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10999           throw INTERP_KERNEL::Exception(oss.str().c_str());
11000         }
11001       if(lgth>=work[-1])
11002         *work=lgth;
11003       else
11004         {
11005           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11006           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11007           throw INTERP_KERNEL::Exception(oss.str().c_str());
11008         }
11009     }
11010   arro->alloc(lgth,1);
11011   work=arro->getPointer();
11012   idsIt=idsOfSelectStart;
11013   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11014     {
11015       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11016         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11017       else
11018         {
11019           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11020           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11021           throw INTERP_KERNEL::Exception(oss.str().c_str());
11022         }
11023     }
11024   arrOut=arro.retn();
11025   arrIndexOut=arrIo.retn();
11026 }
11027
11028 /*!
11029  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11030  * 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
11031  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11032  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11033  *
11034  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11035  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11036  * \param [in] arrIn arr origin array from which the extraction will be done.
11037  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11038  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11039  * \param [in] srcArrIndex index array of \b srcArr
11040  * \param [out] arrOut the resulting array
11041  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11042  * 
11043  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11044  */
11045 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11046                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11047                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11048 {
11049   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11051   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11052   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11053   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11054   std::vector<bool> v(nbOfTuples,true);
11055   int offset=0;
11056   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11057   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11058   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11059     {
11060       if(*it>=0 && *it<nbOfTuples)
11061         {
11062           v[*it]=false;
11063           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11064         }
11065       else
11066         {
11067           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11068           throw INTERP_KERNEL::Exception(oss.str().c_str());
11069         }
11070     }
11071   srcArrIndexPtr=srcArrIndex->getConstPointer();
11072   arrIo->alloc(nbOfTuples+1,1);
11073   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11074   const int *arrInPtr=arrIn->getConstPointer();
11075   const int *srcArrPtr=srcArr->getConstPointer();
11076   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11077   int *arroPtr=arro->getPointer();
11078   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11079     {
11080       if(v[ii])
11081         {
11082           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11083           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11084         }
11085       else
11086         {
11087           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11088           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11089           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11090         }
11091     }
11092   arrOut=arro.retn();
11093   arrIndexOut=arrIo.retn();
11094 }
11095
11096 /*!
11097  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11098  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11099  *
11100  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11101  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11102  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11103  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11104  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11105  * \param [in] srcArrIndex index array of \b srcArr
11106  * 
11107  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11108  */
11109 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11110                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11111 {
11112   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11114   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11115   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11116   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11117   int *arrInOutPtr=arrInOut->getPointer();
11118   const int *srcArrPtr=srcArr->getConstPointer();
11119   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11120     {
11121       if(*it>=0 && *it<nbOfTuples)
11122         {
11123           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11124             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11125           else
11126             {
11127               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] !";
11128               throw INTERP_KERNEL::Exception(oss.str().c_str());
11129             }
11130         }
11131       else
11132         {
11133           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11134           throw INTERP_KERNEL::Exception(oss.str().c_str());
11135         }
11136     }
11137 }
11138
11139 /*!
11140  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11141  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11142  * 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]].
11143  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11144  * A negative value in \b arrIn means that it is ignored.
11145  * 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.
11146  * 
11147  * \param [in] arrIn arr origin array from which the extraction will be done.
11148  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11149  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11150  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11151  */
11152 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11153 {
11154   int seed=0,nbOfDepthPeelingPerformed=0;
11155   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11156 }
11157
11158 /*!
11159  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11160  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11161  * 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]].
11162  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11163  * A negative value in \b arrIn means that it is ignored.
11164  * 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.
11165  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11166  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11167  * \param [in] arrIn arr origin array from which the extraction will be done.
11168  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11169  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11170  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11171  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11172  * \sa MEDCouplingUMesh::partitionBySpreadZone
11173  */
11174 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11175 {
11176   nbOfDepthPeelingPerformed=0;
11177   if(!arrIndxIn)
11178     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11179   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11180   if(nbOfTuples<=0)
11181     {
11182       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11183       return ret;
11184     }
11185   //
11186   std::vector<bool> fetched(nbOfTuples,false);
11187   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11188 }
11189
11190 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11191 {
11192   nbOfDepthPeelingPerformed=0;
11193   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11195   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11196   std::vector<bool> fetched2(nbOfTuples,false);
11197   int i=0;
11198   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11199     {
11200       if(*seedElt>=0 && *seedElt<nbOfTuples)
11201         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11202       else
11203         { 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()); }
11204     }
11205   const int *arrInPtr=arrIn->getConstPointer();
11206   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11207   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11208   std::vector<int> idsToFetch1(seedBg,seedEnd);
11209   std::vector<int> idsToFetch2;
11210   std::vector<int> *idsToFetch=&idsToFetch1;
11211   std::vector<int> *idsToFetchOther=&idsToFetch2;
11212   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11213     {
11214       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11215         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11216           if(!fetched[*it2])
11217             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11218       std::swap(idsToFetch,idsToFetchOther);
11219       idsToFetchOther->clear();
11220       nbOfDepthPeelingPerformed++;
11221     }
11222   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11223   i=0;
11224   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11225   int *retPtr=ret->getPointer();
11226   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11227     if(*it)
11228       *retPtr++=i;
11229   return ret.retn();
11230 }
11231
11232 /*!
11233  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11234  * 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
11235  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11236  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11237  *
11238  * \param [in] start begin of set of ids of the input extraction (included)
11239  * \param [in] end end of set of ids of the input extraction (excluded)
11240  * \param [in] step step of the set of ids in range mode.
11241  * \param [in] arrIn arr origin array from which the extraction will be done.
11242  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11243  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11244  * \param [in] srcArrIndex index array of \b srcArr
11245  * \param [out] arrOut the resulting array
11246  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11247  * 
11248  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11249  */
11250 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11251                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11252                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11253 {
11254   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11255     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11256   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11257   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11258   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11259   int offset=0;
11260   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11261   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11262   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11263   int it=start;
11264   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11265     {
11266       if(it>=0 && it<nbOfTuples)
11267         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11268       else
11269         {
11270           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11271           throw INTERP_KERNEL::Exception(oss.str().c_str());
11272         }
11273     }
11274   srcArrIndexPtr=srcArrIndex->getConstPointer();
11275   arrIo->alloc(nbOfTuples+1,1);
11276   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11277   const int *arrInPtr=arrIn->getConstPointer();
11278   const int *srcArrPtr=srcArr->getConstPointer();
11279   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11280   int *arroPtr=arro->getPointer();
11281   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11282     {
11283       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11284       if(pos<0)
11285         {
11286           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11287           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11288         }
11289       else
11290         {
11291           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11292           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11293         }
11294     }
11295   arrOut=arro.retn();
11296   arrIndexOut=arrIo.retn();
11297 }
11298
11299 /*!
11300  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11301  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11302  *
11303  * \param [in] start begin of set of ids of the input extraction (included)
11304  * \param [in] end end of set of ids of the input extraction (excluded)
11305  * \param [in] step step of the set of ids in range mode.
11306  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11307  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11308  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11309  * \param [in] srcArrIndex index array of \b srcArr
11310  * 
11311  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11312  */
11313 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11314                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11315 {
11316   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11317     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11318   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11319   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11320   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11321   int *arrInOutPtr=arrInOut->getPointer();
11322   const int *srcArrPtr=srcArr->getConstPointer();
11323   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11324   int it=start;
11325   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11326     {
11327       if(it>=0 && it<nbOfTuples)
11328         {
11329           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11330             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11331           else
11332             {
11333               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11334               throw INTERP_KERNEL::Exception(oss.str().c_str());
11335             }
11336         }
11337       else
11338         {
11339           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11340           throw INTERP_KERNEL::Exception(oss.str().c_str());
11341         }
11342     }
11343 }
11344
11345 /*!
11346  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11347  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11348  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11349  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11350  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11351  * 
11352  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11353  */
11354 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11355 {
11356   checkFullyDefined();
11357   int mdim=getMeshDimension();
11358   int spaceDim=getSpaceDimension();
11359   if(mdim!=spaceDim)
11360     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11361   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11362   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11363   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11364   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11365   ret->setCoords(getCoords());
11366   ret->allocateCells((int)partition.size());
11367   //
11368   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11369     {
11370       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11371       MCAuto<DataArrayInt> cell;
11372       switch(mdim)
11373       {
11374         case 2:
11375           cell=tmp->buildUnionOf2DMesh();
11376           break;
11377         case 3:
11378           cell=tmp->buildUnionOf3DMesh();
11379           break;
11380         default:
11381           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11382       }
11383
11384       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11385     }
11386   //
11387   ret->finishInsertingCells();
11388   return ret.retn();
11389 }
11390
11391 /*!
11392  * This method partitions \b this into contiguous zone.
11393  * This method only needs a well defined connectivity. Coordinates are not considered here.
11394  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11395  */
11396 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11397 {
11398   int nbOfCellsCur=getNumberOfCells();
11399   std::vector<DataArrayInt *> ret;
11400   if(nbOfCellsCur<=0)
11401     return ret;
11402   DataArrayInt *neigh=0,*neighI=0;
11403   computeNeighborsOfCells(neigh,neighI);
11404   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11405   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11406   std::vector< MCAuto<DataArrayInt> > ret2;
11407   int seed=0;
11408   while(seed<nbOfCellsCur)
11409     {
11410       int nbOfPeelPerformed=0;
11411       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11412       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11413     }
11414   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11415     ret.push_back((*it).retn());
11416   return ret;
11417 }
11418
11419 /*!
11420  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11421  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11422  *
11423  * \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.
11424  * \return a newly allocated DataArrayInt to be managed by the caller.
11425  * \throw In case of \a code has not the right format (typically of size 3*n)
11426  */
11427 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11428 {
11429   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11430   std::size_t nb=code.size()/3;
11431   if(code.size()%3!=0)
11432     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11433   ret->alloc((int)nb,2);
11434   int *retPtr=ret->getPointer();
11435   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11436     {
11437       retPtr[0]=code[3*i+2];
11438       retPtr[1]=code[3*i+2]+code[3*i+1];
11439     }
11440   return ret.retn();
11441 }
11442
11443 /*!
11444  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11445  * All cells in \a this are expected to be linear 3D cells.
11446  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11447  * It leads to an increase to number of cells.
11448  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11449  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11450  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11451  *
11452  * \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.
11453  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11454  * \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. 
11455  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11456  *          an id of old cell producing it. The caller is to delete this array using
11457  *         decrRef() as it is no more needed.
11458  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11459  *
11460  * \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
11461  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11462  * 
11463  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11464  * \throw If \a this is not fully constituted with linear 3D cells.
11465  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11466  */
11467 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11468 {
11469   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11470   checkConnectivityFullyDefined();
11471   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11473   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11474   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11475   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11476   int *retPt(ret->getPointer());
11477   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11478   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11479   const int *oldc(_nodal_connec->begin());
11480   const int *oldci(_nodal_connec_index->begin());
11481   const double *coords(_coords->begin());
11482   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11483     {
11484       std::vector<int> a; std::vector<double> b;
11485       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11486       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11487       const int *aa(&a[0]);
11488       if(!b.empty())
11489         {
11490           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11491             if(*it<0)
11492               *it=(-(*(it))-1+nbNodes);
11493           addPts->insertAtTheEnd(b.begin(),b.end());
11494           nbNodes+=(int)b.size()/3;
11495         }
11496       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11497         newConn->insertAtTheEnd(aa,aa+4);
11498     }
11499   if(!addPts->empty())
11500     {
11501       addPts->rearrange(3);
11502       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11503       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11504       ret0->setCoords(addPts);
11505     }
11506   else
11507     {
11508       nbOfAdditionalPoints=0;
11509       ret0->setCoords(getCoords());
11510     }
11511   ret0->setNodalConnectivity(newConn);
11512   //
11513   ret->computeOffsetsFull();
11514   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11515   return ret0.retn();
11516 }
11517
11518 /*!
11519  * 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). 
11520  *
11521  * \sa MEDCouplingUMesh::split2DCells
11522  */
11523 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11524 {
11525   checkConnectivityFullyDefined();
11526   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11527   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11528   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11529   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11530   int prevPosOfCi(ciPtr[0]);
11531   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11532     {
11533       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11534       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11535       for(int j=0;j<sz;j++)
11536         {
11537           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11538           for(int k=0;k<sz2;k++)
11539             *cPtr++=subPtr[offset2+k];
11540           if(j!=sz-1)
11541             *cPtr++=oldConn[prevPosOfCi+j+2];
11542           deltaSz+=sz2;
11543         }
11544       prevPosOfCi=ciPtr[1];
11545       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11546     }
11547   if(c->end()!=cPtr)
11548     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11549   _nodal_connec->decrRef();
11550   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11551 }
11552
11553 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11554 {
11555   if(id!=-1)
11556     return id;
11557   else
11558     {
11559       int ret(nodesCnter++);
11560       double newPt[2];
11561       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11562       addCoo.insertAtTheEnd(newPt,newPt+2);
11563       return ret;
11564     }
11565 }
11566
11567 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11568 {
11569   if(id!=-1)
11570     return id;
11571   else
11572     {
11573       int ret(nodesCnter++);
11574       double newPt[2];
11575       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11576       addCoo.insertAtTheEnd(newPt,newPt+2);
11577       return ret;
11578     }
11579 }
11580
11581
11582 /// @cond INTERNAL
11583
11584 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)
11585 {
11586   int tmp[3];
11587   int trueStart(start>=0?start:nbOfEdges+start);
11588   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11589   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11590   if(linOrArc)
11591     {
11592       if(stp-start>1)
11593         {
11594           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11595           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11596           middles.push_back(tmp3+offset);
11597         }
11598       else
11599         middles.push_back(connBg[trueStart+nbOfEdges]);
11600     }
11601 }
11602
11603 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)
11604 {
11605   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11606   newConnOfCell->pushBackSilent(tmpEnd);
11607   if(linOrArc)
11608     {
11609       if(stp-start>1)
11610         {
11611           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11612           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11613           middles.push_back(tmp3+offset);
11614         }
11615       else
11616         middles.push_back(connBg[start+nbOfEdges]);
11617     }
11618 }
11619
11620 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)
11621 {
11622   // only the quadratic point to deal with:
11623   if(linOrArc)
11624     {
11625       if(stp-start>1)
11626         {
11627           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11628           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11629           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11630           middles.push_back(tmp3+offset);
11631         }
11632       else
11633         middles.push_back(connBg[start+nbOfEdges]);
11634     }
11635 }
11636
11637 /// @endcond
11638
11639 /*!
11640  * 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 ) .
11641  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11642  */
11643 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11644 {
11645   std::size_t sz(std::distance(connBg,connEnd));
11646   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11647     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11648   sz--;
11649   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11650   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11651   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11652   unsigned nbOfHit(0); // number of fusions operated
11653   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11654   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
11655   INTERP_KERNEL::NormalizedCellType typeOfSon;
11656   std::vector<int> middles;
11657   bool ret(false);
11658   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11659     {
11660       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11661       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11662       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11663       posEndElt = posBaseElt+1;
11664
11665       // Look backward first: are the final edges of the cells colinear with the first ones?
11666       // This initializes posBaseElt.
11667       if(nbOfTurn==0)
11668         {
11669           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11670             {
11671               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11672               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11673               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11674               bool isColinear=eint->areColinears();
11675               if(isColinear)
11676                 {
11677                   nbOfHit++;
11678                   posBaseElt--;
11679                   ret=true;
11680                 }
11681               delete eint;
11682               eCand->decrRef();
11683               if(!isColinear)
11684                 break;
11685             }
11686         }
11687       // Now move forward:
11688       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11689       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11690         {
11691           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11692           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11693           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11694           bool isColinear(eint->areColinears());
11695           if(isColinear)
11696             {
11697               nbOfHit++;
11698               posEndElt++;
11699               ret=true;
11700             }
11701           delete eint;
11702           eCand->decrRef();
11703           if(!isColinear)
11704               break;
11705         }
11706       //push [posBaseElt,posEndElt) in newConnOfCell using e
11707       // 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!
11708       if(nbOfTurn==0)
11709         // at the begining of the connectivity (insert type)
11710         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11711       else if((nbOfHit+nbOfTurn) != (nbs-1))
11712         // in the middle
11713         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11714       if ((nbOfHit+nbOfTurn) == (nbs-1))
11715         // at the end (only quad points to deal with)
11716         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11717       posBaseElt=posEndElt;
11718       e->decrRef();
11719     }
11720   if(!middles.empty())
11721     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11722   return ret;
11723 }
11724
11725 /*!
11726  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11727  *
11728  * \return  int - the number of new nodes created.
11729  * \sa MEDCouplingUMesh::split2DCells
11730  */
11731 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11732 {
11733   checkConsistencyLight();
11734   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11735   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11736   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11737   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11738   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11739   const double *oldCoordsPtr(getCoords()->begin());
11740   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11741   int prevPosOfCi(ciPtr[0]);
11742   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11743     {
11744       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11745       for(int j=0;j<sz;j++)
11746         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11747       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11748       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11749         {
11750           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11751           if(sz2==0)
11752             {
11753               if(j<sz-1)
11754                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11755               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11756               continue;
11757             }
11758           std::vector<INTERP_KERNEL::Node *> ns(3);
11759           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11760           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11761           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11762           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11763           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11764             {
11765               cPtr[1]=subPtr[offset2+k];
11766               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11767             }
11768           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11769           if(j!=sz-1)
11770             { cPtr[1]=tmpEnd; }
11771           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11772         }
11773       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11774       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11775     }
11776   if(c->end()!=cPtr)
11777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11778   _nodal_connec->decrRef();
11779   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11780   addCoo->rearrange(2);
11781   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11782   setCoords(coo);
11783   return addCoo->getNumberOfTuples();
11784 }
11785
11786 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11787 {
11788   if(nodalConnec && nodalConnecIndex)
11789     {
11790       types.clear();
11791       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11792       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11793       if(nbOfElem>0)
11794         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11795           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11796     }
11797 }
11798
11799 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11800     _own_cell(true),_cell_id(-1),_nb_cell(0)
11801 {
11802   if(mesh)
11803     {
11804       mesh->incrRef();
11805       _nb_cell=mesh->getNumberOfCells();
11806     }
11807 }
11808
11809 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11810 {
11811   if(_mesh)
11812     _mesh->decrRef();
11813   if(_own_cell)
11814     delete _cell;
11815 }
11816
11817 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11818     _own_cell(false),_cell_id(bg-1),
11819     _nb_cell(end)
11820 {
11821   if(mesh)
11822     mesh->incrRef();
11823 }
11824
11825 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11826 {
11827   _cell_id++;
11828   if(_cell_id<_nb_cell)
11829     {
11830       _cell->next();
11831       return _cell;
11832     }
11833   else
11834     return 0;
11835 }
11836
11837 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11838 {
11839   if(_mesh)
11840     _mesh->incrRef();
11841 }
11842
11843 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11844 {
11845   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11846 }
11847
11848 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11849 {
11850   if(_mesh)
11851     _mesh->decrRef();
11852 }
11853
11854 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11855     _itc(itc),
11856     _bg(bg),_end(end)
11857 {
11858   if(_mesh)
11859     _mesh->incrRef();
11860 }
11861
11862 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11863 {
11864   if(_mesh)
11865     _mesh->decrRef();
11866 }
11867
11868 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11869 {
11870   return _type;
11871 }
11872
11873 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11874 {
11875   return _end-_bg;
11876 }
11877
11878 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11879 {
11880   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11881 }
11882
11883 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11884 {
11885   if(mesh)
11886     {
11887       mesh->incrRef();
11888       _nb_cell=mesh->getNumberOfCells();
11889     }
11890 }
11891
11892 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11893 {
11894   if(_mesh)
11895     _mesh->decrRef();
11896   delete _cell;
11897 }
11898
11899 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11900 {
11901   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11902   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11903   if(_cell_id<_nb_cell)
11904     {
11905       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11906       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
11907       int startId=_cell_id;
11908       _cell_id+=nbOfElems;
11909       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11910     }
11911   else
11912     return 0;
11913 }
11914
11915 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11916 {
11917   if(mesh)
11918     {
11919       _conn=mesh->getNodalConnectivity()->getPointer();
11920       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11921     }
11922 }
11923
11924 void MEDCouplingUMeshCell::next()
11925 {
11926   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11927     {
11928       _conn+=_conn_lgth;
11929       _conn_indx++;
11930     }
11931   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11932 }
11933
11934 std::string MEDCouplingUMeshCell::repr() const
11935 {
11936   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11937     {
11938       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11939       oss << " : ";
11940       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11941       return oss.str();
11942     }
11943   else
11944     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11945 }
11946
11947 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11948 {
11949   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11950     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11951   else
11952     return INTERP_KERNEL::NORM_ERROR;
11953 }
11954
11955 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11956 {
11957   lgth=_conn_lgth;
11958   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11959     return _conn;
11960   else
11961     return 0;
11962 }