]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDCoupling/MEDCouplingUMesh.cxx
Salome HOME
0022875: EDF 7690 MED: Creating joints with medpartitioner in the MEDCoupling API
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace ParaMEDMEM;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 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 };
57
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
59 {
60   return new MEDCouplingUMesh;
61 }
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
64 {
65   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66   ret->setName(meshName);
67   ret->setMeshDimension(meshDim);
68   return ret;
69 }
70
71 /*!
72  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73  * between \a this and the new mesh.
74  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75  *          delete this mesh using decrRef() as it is no more needed. 
76  */
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
78 {
79   return clone(true);
80 }
81
82 /*!
83  * Returns a new MEDCouplingMesh which is a copy of \a this one.
84  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85  * this mesh are shared by the new mesh.
86  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87  *          delete this mesh using decrRef() as it is no more needed. 
88  */
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
90 {
91   return new MEDCouplingUMesh(*this,recDeepCpy);
92 }
93
94 /*!
95  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96  * The coordinates are shared between \a this and the returned instance.
97  * 
98  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99  * \sa MEDCouplingUMesh::deepCpy
100  */
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
102 {
103   checkConnectivityFullyDefined();
104   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106   ret->setConnectivity(c,ci);
107   return ret.retn();
108 }
109
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 {
112   if(!other)
113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
115   if(!otherC)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 }
120
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
122 {
123   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
124   return ret;
125 }
126
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
128 {
129   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130   ret.push_back(_nodal_connec);
131   ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
248           {
249             std::ostringstream oss;
250             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
251             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252             throw INTERP_KERNEL::Exception(oss.str().c_str());
253           }
254       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
255         {
256           int nodeId=*w;
257           if(nodeId>=0)
258             {
259               if(nodeId>=nbOfNodes)
260                 {
261                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262                   throw INTERP_KERNEL::Exception(oss.str().c_str());
263                 }
264             }
265           else if(nodeId<-1)
266             {
267               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268               throw INTERP_KERNEL::Exception(oss.str().c_str());
269             }
270           else
271             {
272               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
273                 {
274                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275                   throw INTERP_KERNEL::Exception(oss.str().c_str());
276                 }
277             }
278         }
279     }
280 }
281
282
283 /*!
284  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285  * then \a this mesh is most probably is writable, exchangeable and available for all
286  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
287  *  \param [in] eps - a not used parameter.
288  *  \throw If the mesh dimension is not set.
289  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
290  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291  *  \throw If the connectivity data array has more than one component.
292  *  \throw If the connectivity data array has a named component.
293  *  \throw If the connectivity index data array has more than one component.
294  *  \throw If the connectivity index data array has a named component.
295  *  \throw If number of nodes defining an element does not correspond to the type of element.
296  *  \throw If the nodal connectivity includes an invalid node id.
297  */
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
299 {
300   checkCoherency1(eps);
301 }
302
303 /*!
304  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305  * elements contained in the mesh. For more info on the mesh dimension see
306  * \ref MEDCouplingUMeshPage.
307  *  \param [in] meshDim - a new mesh dimension.
308  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
309  */
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
311 {
312   if(meshDim<-1 || meshDim>3)
313     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
314   _mesh_dim=meshDim;
315   declareAsNew();
316 }
317
318 /*!
319  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
320  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
321  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
322  *
323  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
324  *
325  *  \if ENABLE_EXAMPLES
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  *  \endif
329  */
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
331 {
332   if(nbOfCells<0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334   if(_nodal_connec_index)
335     {
336       _nodal_connec_index->decrRef();
337     }
338   if(_nodal_connec)
339     {
340       _nodal_connec->decrRef();
341     }
342   _nodal_connec_index=DataArrayInt::New();
343   _nodal_connec_index->reserve(nbOfCells+1);
344   _nodal_connec_index->pushBackSilent(0);
345   _nodal_connec=DataArrayInt::New();
346   _nodal_connec->reserve(2*nbOfCells);
347   _types.clear();
348   declareAsNew();
349 }
350
351 /*!
352  * Appends a cell to the connectivity array. For deeper understanding what is
353  * happening see \ref MEDCouplingUMeshNodalConnectivity.
354  *  \param [in] type - type of cell to add.
355  *  \param [in] size - number of nodes constituting this cell.
356  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
357  * 
358  *  \if ENABLE_EXAMPLES
359  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
361  *  \endif
362  */
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
364 {
365   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366   if(_nodal_connec_index==0)
367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368   if((int)cm.getDimension()==_mesh_dim)
369     {
370       if(!cm.isDynamic())
371         if(size!=(int)cm.getNumberOfNodes())
372           {
373             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375             throw INTERP_KERNEL::Exception(oss.str().c_str());
376           }
377       int idx=_nodal_connec_index->back();
378       int val=idx+size+1;
379       _nodal_connec_index->pushBackSilent(val);
380       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
381       _types.insert(type);
382     }
383   else
384     {
385       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388       throw INTERP_KERNEL::Exception(oss.str().c_str());
389     }
390 }
391
392 /*!
393  * Compacts data arrays to release unused memory. This method is to be called after
394  * finishing cell insertion using \a this->insertNextCell().
395  * 
396  *  \if ENABLE_EXAMPLES
397  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
399  *  \endif
400  */
401 void MEDCouplingUMesh::finishInsertingCells()
402 {
403   _nodal_connec->pack();
404   _nodal_connec_index->pack();
405   _nodal_connec->declareAsNew();
406   _nodal_connec_index->declareAsNew();
407   updateTime();
408 }
409
410 /*!
411  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412  * Useful for python users.
413  */
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
415 {
416   return new MEDCouplingUMeshCellIterator(this);
417 }
418
419 /*!
420  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423  * Useful for python users.
424  */
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
426 {
427   if(!checkConsecutiveCellTypes())
428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429   return new MEDCouplingUMeshCellByTypeEntry(this);
430 }
431
432 /*!
433  * Returns a set of all cell types available in \a this mesh.
434  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435  * \warning this method does not throw any exception even if \a this is not defined.
436  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
437  */
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
439 {
440   return _types;
441 }
442
443 /*!
444  * This method returns the sorted list of geometric types in \a this.
445  * 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
446  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
447  *
448  * \throw if connectivity in \a this is not correctly defined.
449  *  
450  * \sa MEDCouplingMesh::getAllGeoTypes
451  */
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
453 {
454   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455   checkConnectivityFullyDefined();
456   int nbOfCells(getNumberOfCells());
457   if(nbOfCells==0)
458     return ret;
459   if(getMeshLength()<1)
460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463   for(int i=1;i<nbOfCells;i++,ci++)
464     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
466   return ret;
467 }
468
469 /*!
470  * This method is a method that compares \a this and \a other.
471  * This method compares \b all attributes, even names and component names.
472  */
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
474 {
475   if(!other)
476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477   std::ostringstream oss; oss.precision(15);
478   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
479   if(!otherC)
480     {
481       reason="mesh given in input is not castable in MEDCouplingUMesh !";
482       return false;
483     }
484   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
485     return false;
486   if(_mesh_dim!=otherC->_mesh_dim)
487     {
488       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
489       reason=oss.str();
490       return false;
491     }
492   if(_types!=otherC->_types)
493     {
494       oss << "umesh geometric type mismatch :\nThis geometric types are :";
495       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497       oss << "\nOther geometric types are :";
498       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500       reason=oss.str();
501       return false;
502     }
503   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504     if(_nodal_connec==0 || otherC->_nodal_connec==0)
505       {
506         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
507         return false;
508       }
509   if(_nodal_connec!=otherC->_nodal_connec)
510     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
511       {
512         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
513         return false;
514       }
515   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
517       {
518         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
519         return false;
520       }
521   if(_nodal_connec_index!=otherC->_nodal_connec_index)
522     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
523       {
524         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
525         return false;
526       }
527   return true;
528 }
529
530 /*!
531  * Checks if data arrays of this mesh (node coordinates, nodal
532  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
533  * not considered.
534  *  \param [in] other - the mesh to compare with.
535  *  \param [in] prec - precision value used to compare node coordinates.
536  *  \return bool - \a true if the two meshes are same.
537  */
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
539 {
540   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
541   if(!otherC)
542     return false;
543   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
544     return false;
545   if(_mesh_dim!=otherC->_mesh_dim)
546     return false;
547   if(_types!=otherC->_types)
548     return false;
549   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550     if(_nodal_connec==0 || otherC->_nodal_connec==0)
551       return false;
552   if(_nodal_connec!=otherC->_nodal_connec)
553     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
554       return false;
555   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
557       return false;
558   if(_nodal_connec_index!=otherC->_nodal_connec_index)
559     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
560       return false;
561   return true;
562 }
563
564 /*!
565  * Checks if \a this and \a other meshes are geometrically equivalent with high
566  * probability, else an exception is thrown. The meshes are considered equivalent if
567  * (1) meshes contain the same number of nodes and the same number of elements of the
568  * same types (2) three cells of the two meshes (first, last and middle) are based
569  * on coincident nodes (with a specified precision).
570  *  \param [in] other - the mesh to compare with.
571  *  \param [in] prec - the precision used to compare nodes of the two meshes.
572  *  \throw If the two meshes do not match.
573  */
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
575 {
576   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
578   if(!otherC)
579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
580 }
581
582 /*!
583  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584  * cells each node belongs to.
585  * \warning For speed reasons, this method does not check if node ids in the nodal
586  *          connectivity correspond to the size of node coordinates array.
587  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589  *        dividing cell ids in \a revNodal into groups each referring to one
590  *        node. Its every element (except the last one) is an index pointing to the
591  *         first id of a group of cells. For example cells sharing the node #1 are 
592  *        described by following range of indices: 
593  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595  *        Number of cells sharing the *i*-th node is
596  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597  * \throw If the coordinates array is not set.
598  * \throw If the nodal connectivity of cells is not defined.
599  * 
600  * \if ENABLE_EXAMPLES
601  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
603  * \endif
604  */
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
606 {
607   checkFullyDefined();
608   int nbOfNodes=getNumberOfNodes();
609   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612   const int *conn=_nodal_connec->getConstPointer();
613   const int *connIndex=_nodal_connec_index->getConstPointer();
614   int nbOfCells=getNumberOfCells();
615   int nbOfEltsInRevNodal=0;
616   for(int eltId=0;eltId<nbOfCells;eltId++)
617     {
618       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621         if(*iter>=0)//for polyhedrons
622           {
623             nbOfEltsInRevNodal++;
624             revNodalIndxPtr[(*iter)+1]++;
625           }
626     }
627   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631   for(int eltId=0;eltId<nbOfCells;eltId++)
632     {
633       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636         if(*iter>=0)//for polyhedrons
637           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
638     }
639 }
640
641 /// @cond INTERNAL
642
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 {
645   return id;
646 }
647
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
649 {
650   if(!compute)
651     return id+1;
652   else
653     {
654       if(cm.getOrientationStatus(nb,conn1,conn2))
655         return id+1;
656       else
657         return -(id+1);
658     }
659 }
660
661 class MinusOneSonsGenerator
662 {
663 public:
664   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667   static const int DELTA=1;
668 private:
669   const INTERP_KERNEL::CellModel& _cm;
670 };
671
672 class MinusOneSonsGeneratorBiQuadratic
673 {
674 public:
675   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678   static const int DELTA=1;
679 private:
680   const INTERP_KERNEL::CellModel& _cm;
681 };
682
683 class MinusTwoSonsGenerator
684 {
685 public:
686   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689   static const int DELTA=2;
690 private:
691   const INTERP_KERNEL::CellModel& _cm;
692 };
693
694 /// @endcond
695
696 /*!
697  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699  * describing correspondence between cells of \a this and the result meshes are
700  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
701  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
703  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
704  * \warning For speed reasons, this method does not check if node ids in the nodal
705  *          connectivity correspond to the size of node coordinates array.
706  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707  *          to write this mesh to the MED file, its cells must be sorted using
708  *          sortCellsInMEDFileFrmt().
709  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
710  *         each cell of \a this mesh.
711  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712  *        dividing cell ids in \a desc into groups each referring to one
713  *        cell of \a this mesh. Its every element (except the last one) is an index
714  *        pointing to the first id of a group of cells. For example cells of the
715  *        result mesh bounding the cell #1 of \a this mesh are described by following
716  *        range of indices:
717  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722  *         by each cell of the result mesh.
723  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
724  *        in the result mesh,
725  *        dividing cell ids in \a revDesc into groups each referring to one
726  *        cell of the result mesh the same way as \a descIndx divides \a desc.
727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728  *        delete this mesh using decrRef() as it is no more needed.
729  *  \throw If the coordinates array is not set.
730  *  \throw If the nodal connectivity of cells is node defined.
731  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732  *         revDescIndx == NULL.
733  * 
734  *  \if ENABLE_EXAMPLES
735  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
737  *  \endif
738  * \sa buildDescendingConnectivity2()
739  */
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
741 {
742   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 }
744
745 /*!
746  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750  * \sa MEDCouplingUMesh::buildDescendingConnectivity
751  */
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
753 {
754   checkFullyDefined();
755   if(getMeshDimension()!=3)
756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
758 }
759
760 /*!
761  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762  * this->getMeshDimension(), that bound cells of \a this mesh. In
763  * addition arrays describing correspondence between cells of \a this and the result
764  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
765  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766  *  mesh. This method differs from buildDescendingConnectivity() in that apart
767  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768  * result meshes. So a positive id means that order of nodes in corresponding cells
769  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771  * i.e. cell ids are one-based.
772  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
773  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
774  * \warning For speed reasons, this method does not check if node ids in the nodal
775  *          connectivity correspond to the size of node coordinates array.
776  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777  *          to write this mesh to the MED file, its cells must be sorted using
778  *          sortCellsInMEDFileFrmt().
779  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
780  *         each cell of \a this mesh.
781  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782  *        dividing cell ids in \a desc into groups each referring to one
783  *        cell of \a this mesh. Its every element (except the last one) is an index
784  *        pointing to the first id of a group of cells. For example cells of the
785  *        result mesh bounding the cell #1 of \a this mesh are described by following
786  *        range of indices:
787  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792  *         by each cell of the result mesh.
793  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
794  *        in the result mesh,
795  *        dividing cell ids in \a revDesc into groups each referring to one
796  *        cell of the result mesh the same way as \a descIndx divides \a desc.
797  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798  *        shares the node coordinates array with \a this mesh. The caller is to
799  *        delete this mesh using decrRef() as it is no more needed.
800  *  \throw If the coordinates array is not set.
801  *  \throw If the nodal connectivity of cells is node defined.
802  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803  *         revDescIndx == NULL.
804  * 
805  *  \if ENABLE_EXAMPLES
806  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
808  *  \endif
809  * \sa buildDescendingConnectivity()
810  */
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
812 {
813   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
814 }
815
816 /*!
817  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
819  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
820  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
821  *
822  * \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
823  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
824  * \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.
825  */
826 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
827 {
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
832   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
833   meshDM1=0;
834   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
835 }
836
837 /*!
838  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
839  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
840  * excluding a set of meshdim-1 cells in input descending connectivity.
841  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
842  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
843  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
844  *
845  * \param [in] desc descending connectivity array.
846  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
847  * \param [in] revDesc reverse descending connectivity array.
848  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
849  * \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
850  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
851  * \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.
852  */
853 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
854                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
855 {
856   if(!desc || !descIndx || !revDesc || !revDescIndx)
857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
858   const int *descPtr=desc->getConstPointer();
859   const int *descIPtr=descIndx->getConstPointer();
860   const int *revDescPtr=revDesc->getConstPointer();
861   const int *revDescIPtr=revDescIndx->getConstPointer();
862   //
863   int nbCells=descIndx->getNumberOfTuples()-1;
864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
866   int *out1Ptr=out1->getPointer();
867   *out1Ptr++=0;
868   out0->reserve(desc->getNumberOfTuples());
869   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
870     {
871       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
872         {
873           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
874           s.erase(i);
875           out0->insertAtTheEnd(s.begin(),s.end());
876         }
877       *out1Ptr=out0->getNumberOfTuples();
878     }
879   neighbors=out0.retn();
880   neighborsIndx=out1.retn();
881 }
882
883 /*!
884  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
885  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
886  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
887  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
888  *
889  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
890  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
891  * \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.
892  */
893 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
894 {
895   checkFullyDefined();
896   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
899   switch(mdim)
900   {
901     case 3:
902       {
903         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
904         break;
905       }
906     case 2:
907       {
908         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
909         break;
910       }
911     case 1:
912       {
913         mesh1D=const_cast<MEDCouplingUMesh *>(this);
914         mesh1D->incrRef();
915         break;
916       }
917     default:
918       {
919         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
920       }
921   }
922   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
923   mesh1D->getReverseNodalConnectivity(desc,descIndx);
924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
925   ret0->alloc(desc->getNumberOfTuples(),1);
926   int *r0Pt(ret0->getPointer());
927   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
928   for(int i=0;i<nbNodes;i++,rni++)
929     {
930       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
931         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
932     }
933   neighbors=ret0.retn();
934   neighborsIdx=descIndx.retn();
935 }
936
937 /// @cond INTERNAL
938
939 /*!
940  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
941  * For speed reasons no check of this will be done.
942  */
943 template<class SonsGenerator>
944 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
945 {
946   if(!desc || !descIndx || !revDesc || !revDescIndx)
947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
948   checkConnectivityFullyDefined();
949   int nbOfCells=getNumberOfCells();
950   int nbOfNodes=getNumberOfNodes();
951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
952   int *revNodalIndxPtr=revNodalIndx->getPointer();
953   const int *conn=_nodal_connec->getConstPointer();
954   const int *connIndex=_nodal_connec_index->getConstPointer();
955   std::string name="Mesh constituent of "; name+=getName();
956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
957   ret->setCoords(getCoords());
958   ret->allocateCells(2*nbOfCells);
959   descIndx->alloc(nbOfCells+1,1);
960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
961   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
962   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
963     {
964       int pos=connIndex[eltId];
965       int posP1=connIndex[eltId+1];
966       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
967       SonsGenerator sg(cm);
968       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
969       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
970       for(unsigned i=0;i<nbOfSons;i++)
971         {
972           INTERP_KERNEL::NormalizedCellType cmsId;
973           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
974           for(unsigned k=0;k<nbOfNodesSon;k++)
975             if(tmp[k]>=0)
976               revNodalIndxPtr[tmp[k]+1]++;
977           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
978           revDesc2->pushBackSilent(eltId);
979         }
980       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
981     }
982   int nbOfCellsM1=ret->getNumberOfCells();
983   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
985   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
986   int *revNodalPtr=revNodal->getPointer();
987   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
988   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
989   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
990     {
991       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
992       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
993       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
994         if(*iter>=0)//for polyhedrons
995           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
996     }
997   //
998   DataArrayInt *commonCells=0,*commonCellsI=0;
999   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1001   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1002   int newNbOfCellsM1=-1;
1003   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1004                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1005   std::vector<bool> isImpacted(nbOfCellsM1,false);
1006   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1007     for(int work2=work[0];work2!=work[1];work2++)
1008       isImpacted[commonCellsPtr[work2]]=true;
1009   const int *o2nM1Ptr=o2nM1->getConstPointer();
1010   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1011   const int *n2oM1Ptr=n2oM1->getConstPointer();
1012   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1013   ret2->copyTinyInfoFrom(this);
1014   desc->alloc(descIndx->back(),1);
1015   int *descPtr=desc->getPointer();
1016   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1017   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1018     {
1019       if(!isImpacted[i])
1020         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1021       else
1022         {
1023           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1024             {
1025               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1026               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1027             }
1028           else
1029             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1030         }
1031     }
1032   revDesc->reserve(newNbOfCellsM1);
1033   revDescIndx->alloc(newNbOfCellsM1+1,1);
1034   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1035   const int *revDesc2Ptr=revDesc2->getConstPointer();
1036   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1037     {
1038       int oldCellIdM1=n2oM1Ptr[i];
1039       if(!isImpacted[oldCellIdM1])
1040         {
1041           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1042           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1043         }
1044       else
1045         {
1046           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1047             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1048           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1049           commonCellsIPtr++;
1050         }
1051     }
1052   //
1053   return ret2.retn();
1054 }
1055
1056 struct MEDCouplingAccVisit
1057 {
1058   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1059   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1060   int _new_nb_of_nodes;
1061 };
1062
1063 /// @endcond
1064
1065 /*!
1066  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1067  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1068  * array of cell ids. Pay attention that after conversion all algorithms work slower
1069  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1070  * conversion due presence of invalid ids in the array of cells to convert, as a
1071  * result \a this mesh contains some already converted elements. In this case the 2D
1072  * mesh remains valid but 3D mesh becomes \b inconsistent!
1073  *  \warning This method can significantly modify the order of geometric types in \a this,
1074  *          hence, to write this mesh to the MED file, its cells must be sorted using
1075  *          sortCellsInMEDFileFrmt().
1076  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1077  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1078  *         cellIdsToConvertBg.
1079  *  \throw If the coordinates array is not set.
1080  *  \throw If the nodal connectivity of cells is node defined.
1081  *  \throw If dimension of \a this mesh is not either 2 or 3.
1082  *
1083  *  \if ENABLE_EXAMPLES
1084  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1085  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1086  *  \endif
1087  */
1088 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1089 {
1090   checkFullyDefined();
1091   int dim=getMeshDimension();
1092   if(dim<2 || dim>3)
1093     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1094   int nbOfCells(getNumberOfCells());
1095   if(dim==2)
1096     {
1097       const int *connIndex=_nodal_connec_index->getConstPointer();
1098       int *conn=_nodal_connec->getPointer();
1099       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1100         {
1101           if(*iter>=0 && *iter<nbOfCells)
1102             {
1103               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1104               if(!cm.isQuadratic())
1105                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1106               else
1107                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1108             }
1109           else
1110             {
1111               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1112               oss << " in range [0," << nbOfCells << ") !";
1113               throw INTERP_KERNEL::Exception(oss.str().c_str());
1114             }
1115         }
1116     }
1117   else
1118     {
1119       int *connIndex(_nodal_connec_index->getPointer());
1120       const int *connOld(_nodal_connec->getConstPointer());
1121       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1122       std::vector<bool> toBeDone(nbOfCells,false);
1123       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1124         {
1125           if(*iter>=0 && *iter<nbOfCells)
1126             toBeDone[*iter]=true;
1127           else
1128             {
1129               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130               oss << " in range [0," << nbOfCells << ") !";
1131               throw INTERP_KERNEL::Exception(oss.str().c_str());
1132             }
1133         }
1134       for(int cellId=0;cellId<nbOfCells;cellId++)
1135         {
1136           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1137           int lgthOld(posP1-pos-1);
1138           if(toBeDone[cellId])
1139             {
1140               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1141               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1142               int *tmp(new int[nbOfFaces*lgthOld+1]);
1143               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1144               for(unsigned j=0;j<nbOfFaces;j++)
1145                 {
1146                   INTERP_KERNEL::NormalizedCellType type;
1147                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1148                   work+=offset;
1149                   *work++=-1;
1150                 }
1151               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1152               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1153               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1154               delete [] tmp;
1155             }
1156           else
1157             {
1158               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1159               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1160             }
1161         }
1162       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1163     }
1164   computeTypes();
1165 }
1166
1167 /*!
1168  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1169  * polyhedrons (if \a this is a 3D mesh).
1170  *  \warning As this method is purely for user-friendliness and no optimization is
1171  *          done to avoid construction of a useless vector, this method can be costly
1172  *          in memory.
1173  *  \throw If the coordinates array is not set.
1174  *  \throw If the nodal connectivity of cells is node defined.
1175  *  \throw If dimension of \a this mesh is not either 2 or 3.
1176  */
1177 void MEDCouplingUMesh::convertAllToPoly()
1178 {
1179   int nbOfCells=getNumberOfCells();
1180   std::vector<int> cellIds(nbOfCells);
1181   for(int i=0;i<nbOfCells;i++)
1182     cellIds[i]=i;
1183   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1184 }
1185
1186 /*!
1187  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1188  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1189  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1190  * base facet of the volume and the second half of nodes describes an opposite facet
1191  * having the same number of nodes as the base one. This method converts such
1192  * connectivity to a valid polyhedral format where connectivity of each facet is
1193  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1194  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1195  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1196  * a correct orientation of the first facet of a polyhedron, else orientation of a
1197  * corrected cell is reverse.<br>
1198  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1199  * it releases the user from boring description of polyhedra connectivity in the valid
1200  * format.
1201  *  \throw If \a this->getMeshDimension() != 3.
1202  *  \throw If \a this->getSpaceDimension() != 3.
1203  *  \throw If the nodal connectivity of cells is not defined.
1204  *  \throw If the coordinates array is not set.
1205  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1206  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1207  *
1208  *  \if ENABLE_EXAMPLES
1209  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1210  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1211  *  \endif
1212  */
1213 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1214 {
1215   checkFullyDefined();
1216   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1218   int nbOfCells=getNumberOfCells();
1219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1220   newCi->alloc(nbOfCells+1,1);
1221   int *newci=newCi->getPointer();
1222   const int *ci=_nodal_connec_index->getConstPointer();
1223   const int *c=_nodal_connec->getConstPointer();
1224   newci[0]=0;
1225   for(int i=0;i<nbOfCells;i++)
1226     {
1227       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1228       if(type==INTERP_KERNEL::NORM_POLYHED)
1229         {
1230           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1231             {
1232               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1233               throw INTERP_KERNEL::Exception(oss.str().c_str());
1234             }
1235           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1236           if(n2%2!=0)
1237             {
1238               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 !";
1239               throw INTERP_KERNEL::Exception(oss.str().c_str());
1240             }
1241           int n1=(int)(n2/2);
1242           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)
1243         }
1244       else
1245         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1246     }
1247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1248   newC->alloc(newci[nbOfCells],1);
1249   int *newc=newC->getPointer();
1250   for(int i=0;i<nbOfCells;i++)
1251     {
1252       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1253       if(type==INTERP_KERNEL::NORM_POLYHED)
1254         {
1255           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1256           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1257           *newc++=-1;
1258           for(std::size_t j=0;j<n1;j++)
1259             {
1260               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1261               newc[n1+5*j]=-1;
1262               newc[n1+5*j+1]=c[ci[i]+1+j];
1263               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1264               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1265               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1266             }
1267           newc+=n1*6;
1268         }
1269       else
1270         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1271     }
1272   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1273   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1274 }
1275
1276
1277 /*!
1278  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1279  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1280  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1281  *          to write this mesh to the MED file, its cells must be sorted using
1282  *          sortCellsInMEDFileFrmt().
1283  * \return \c true if at least one cell has been converted, \c false else. In the
1284  *         last case the nodal connectivity remains unchanged.
1285  * \throw If the coordinates array is not set.
1286  * \throw If the nodal connectivity of cells is not defined.
1287  * \throw If \a this->getMeshDimension() < 0.
1288  */
1289 bool MEDCouplingUMesh::unPolyze()
1290 {
1291   checkFullyDefined();
1292   int mdim=getMeshDimension();
1293   if(mdim<0)
1294     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1295   if(mdim<=1)
1296     return false;
1297   int nbOfCells=getNumberOfCells();
1298   if(nbOfCells<1)
1299     return false;
1300   int initMeshLgth=getMeshLength();
1301   int *conn=_nodal_connec->getPointer();
1302   int *index=_nodal_connec_index->getPointer();
1303   int posOfCurCell=0;
1304   int newPos=0;
1305   int lgthOfCurCell;
1306   bool ret=false;
1307   for(int i=0;i<nbOfCells;i++)
1308     {
1309       lgthOfCurCell=index[i+1]-posOfCurCell;
1310       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1313       int newLgth;
1314       if(cm.isDynamic())
1315         {
1316           switch(cm.getDimension())
1317           {
1318             case 2:
1319               {
1320                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1323                 break;
1324               }
1325             case 3:
1326               {
1327                 int nbOfFaces,lgthOfPolyhConn;
1328                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1330                 break;
1331               }
1332             case 1:
1333               {
1334                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1335                 break;
1336               }
1337           }
1338           ret=ret || (newType!=type);
1339           conn[newPos]=newType;
1340           newPos+=newLgth+1;
1341           posOfCurCell=index[i+1];
1342           index[i+1]=newPos;
1343         }
1344       else
1345         {
1346           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347           newPos+=lgthOfCurCell;
1348           posOfCurCell+=lgthOfCurCell;
1349           index[i+1]=newPos;
1350         }
1351     }
1352   if(newPos!=initMeshLgth)
1353     _nodal_connec->reAlloc(newPos);
1354   if(ret)
1355     computeTypes();
1356   return ret;
1357 }
1358
1359 /*!
1360  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1363  *
1364  * \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 
1365  *             precision.
1366  */
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1368 {
1369   checkFullyDefined();
1370   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1373   coords->recenterForMaxPrecision(eps);
1374   //
1375   int nbOfCells=getNumberOfCells();
1376   const int *conn=_nodal_connec->getConstPointer();
1377   const int *index=_nodal_connec_index->getConstPointer();
1378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1379   connINew->alloc(nbOfCells+1,1);
1380   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1382   bool changed=false;
1383   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1384     {
1385       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1386         {
1387           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1388           changed=true;
1389         }
1390       else
1391         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392       *connINewPtr=connNew->getNumberOfTuples();
1393     }
1394   if(changed)
1395     setConnectivity(connNew,connINew,false);
1396 }
1397
1398 /*!
1399  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1400  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1401  * the format of returned DataArrayInt instance.
1402  * 
1403  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1404  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1405  */
1406 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1407 {
1408   checkConnectivityFullyDefined();
1409   int nbOfCells=getNumberOfCells();
1410   const int *connIndex=_nodal_connec_index->getConstPointer();
1411   const int *conn=_nodal_connec->getConstPointer();
1412   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1413   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1414   std::vector<bool> retS(maxElt,false);
1415   for(int i=0;i<nbOfCells;i++)
1416     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1417       if(conn[j]>=0)
1418         retS[conn[j]]=true;
1419   int sz=0;
1420   for(int i=0;i<maxElt;i++)
1421     if(retS[i])
1422       sz++;
1423   DataArrayInt *ret=DataArrayInt::New();
1424   ret->alloc(sz,1);
1425   int *retPtr=ret->getPointer();
1426   for(int i=0;i<maxElt;i++)
1427     if(retS[i])
1428       *retPtr++=i;
1429   return ret;
1430 }
1431
1432 /*!
1433  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1434  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1435  */
1436 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1437 {
1438   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1439   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1440   for(int i=0;i<nbOfCells;i++)
1441     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1442       if(conn[j]>=0)
1443         {
1444           if(conn[j]<nbOfNodes)
1445             nodeIdsInUse[conn[j]]=true;
1446           else
1447             {
1448               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1449               throw INTERP_KERNEL::Exception(oss.str().c_str());
1450             }
1451         }
1452 }
1453
1454 /*!
1455  * Finds nodes not used in any cell and returns an array giving a new id to every node
1456  * by excluding the unused nodes, for which the array holds -1. The result array is
1457  * a mapping in "Old to New" mode. 
1458  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1459  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1460  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1461  *          if the node is unused or a new id else. The caller is to delete this
1462  *          array using decrRef() as it is no more needed.  
1463  *  \throw If the coordinates array is not set.
1464  *  \throw If the nodal connectivity of cells is not defined.
1465  *  \throw If the nodal connectivity includes an invalid id.
1466  *
1467  *  \if ENABLE_EXAMPLES
1468  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1469  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1470  *  \endif
1471  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1472  */
1473 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1474 {
1475   nbrOfNodesInUse=-1;
1476   int nbOfNodes(getNumberOfNodes());
1477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1478   ret->alloc(nbOfNodes,1);
1479   int *traducer=ret->getPointer();
1480   std::fill(traducer,traducer+nbOfNodes,-1);
1481   int nbOfCells=getNumberOfCells();
1482   const int *connIndex=_nodal_connec_index->getConstPointer();
1483   const int *conn=_nodal_connec->getConstPointer();
1484   for(int i=0;i<nbOfCells;i++)
1485     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1486       if(conn[j]>=0)
1487         {
1488           if(conn[j]<nbOfNodes)
1489             traducer[conn[j]]=1;
1490           else
1491             {
1492               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1493               throw INTERP_KERNEL::Exception(oss.str().c_str());
1494             }
1495         }
1496   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1497   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1498   return ret.retn();
1499 }
1500
1501 /*!
1502  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1503  * For each cell in \b this the number of nodes constituting cell is computed.
1504  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1505  * So for pohyhedrons some nodes can be counted several times in the returned result.
1506  * 
1507  * \return a newly allocated array
1508  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1509  */
1510 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1511 {
1512   checkConnectivityFullyDefined();
1513   int nbOfCells=getNumberOfCells();
1514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1515   ret->alloc(nbOfCells,1);
1516   int *retPtr=ret->getPointer();
1517   const int *conn=getNodalConnectivity()->getConstPointer();
1518   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1519   for(int i=0;i<nbOfCells;i++,retPtr++)
1520     {
1521       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1522         *retPtr=connI[i+1]-connI[i]-1;
1523       else
1524         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1525     }
1526   return ret.retn();
1527 }
1528
1529 /*!
1530  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1531  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1532  *
1533  * \return DataArrayInt * - new object to be deallocated by the caller.
1534  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1535  */
1536 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1537 {
1538   checkConnectivityFullyDefined();
1539   int nbOfCells=getNumberOfCells();
1540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1541   ret->alloc(nbOfCells,1);
1542   int *retPtr=ret->getPointer();
1543   const int *conn=getNodalConnectivity()->getConstPointer();
1544   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1545   for(int i=0;i<nbOfCells;i++,retPtr++)
1546     {
1547       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1548       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1549         *retPtr=(int)s.size();
1550       else
1551         {
1552           s.erase(-1);
1553           *retPtr=(int)s.size();
1554         }
1555     }
1556   return ret.retn();
1557 }
1558
1559 /*!
1560  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1561  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1562  * 
1563  * \return a newly allocated array
1564  */
1565 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1566 {
1567   checkConnectivityFullyDefined();
1568   int nbOfCells=getNumberOfCells();
1569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1570   ret->alloc(nbOfCells,1);
1571   int *retPtr=ret->getPointer();
1572   const int *conn=getNodalConnectivity()->getConstPointer();
1573   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1574   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1575     {
1576       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1577       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1578     }
1579   return ret.retn();
1580 }
1581
1582 /*!
1583  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1584  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1585  * array mean that the corresponding old node is no more used. 
1586  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1587  *           this->getNumberOfNodes() before call of this method. The caller is to
1588  *           delete this array using decrRef() as it is no more needed. 
1589  *  \throw If the coordinates array is not set.
1590  *  \throw If the nodal connectivity of cells is not defined.
1591  *  \throw If the nodal connectivity includes an invalid id.
1592  *  \sa areAllNodesFetched
1593  *
1594  *  \if ENABLE_EXAMPLES
1595  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1596  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1597  *  \endif
1598  */
1599 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1600 {
1601   return MEDCouplingPointSet::zipCoordsTraducer();
1602 }
1603
1604 /*!
1605  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1606  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1607  */
1608 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1609 {
1610   switch(compType)
1611   {
1612     case 0:
1613       return AreCellsEqual0(conn,connI,cell1,cell2);
1614     case 1:
1615       return AreCellsEqual1(conn,connI,cell1,cell2);
1616     case 2:
1617       return AreCellsEqual2(conn,connI,cell1,cell2);
1618     case 3:
1619       return AreCellsEqual3(conn,connI,cell1,cell2);
1620     case 7:
1621       return AreCellsEqual7(conn,connI,cell1,cell2);
1622   }
1623   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1633   return 0;
1634 }
1635
1636 /*!
1637  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1638  */
1639 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1640 {
1641   int sz=connI[cell1+1]-connI[cell1];
1642   if(sz==connI[cell2+1]-connI[cell2])
1643     {
1644       if(conn[connI[cell1]]==conn[connI[cell2]])
1645         {
1646           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1647           unsigned dim=cm.getDimension();
1648           if(dim!=3)
1649             {
1650               if(dim!=1)
1651                 {
1652                   int sz1=2*(sz-1);
1653                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1654                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1655                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1656                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1657                   return work!=tmp+sz1?1:0;
1658                 }
1659               else
1660                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1661             }
1662           else
1663             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1664         }
1665     }
1666   return 0;
1667 }
1668
1669 /*!
1670  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1671  */
1672 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1673 {
1674   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1675     {
1676       if(conn[connI[cell1]]==conn[connI[cell2]])
1677         {
1678           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1679           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1680           return s1==s2?1:0;
1681         }
1682     }
1683   return 0;
1684 }
1685
1686 /*!
1687  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1688  */
1689 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1690 {
1691   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1692     {
1693       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1695       return s1==s2?1:0;
1696     }
1697   return 0;
1698 }
1699
1700 /*!
1701  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1702  */
1703 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1704 {
1705   int sz=connI[cell1+1]-connI[cell1];
1706   if(sz==connI[cell2+1]-connI[cell2])
1707     {
1708       if(conn[connI[cell1]]==conn[connI[cell2]])
1709         {
1710           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1711           unsigned dim=cm.getDimension();
1712           if(dim!=3)
1713             {
1714               if(dim!=1)
1715                 {
1716                   int sz1=2*(sz-1);
1717                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1718                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1719                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1720                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1721                   if(work!=tmp+sz1)
1722                     return 1;
1723                   else
1724                     {
1725                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1726                       std::reverse_iterator<int *> it2((int *)tmp);
1727                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1728                         return 2;
1729                       else
1730                         return 0;
1731                     }
1732
1733                   return work!=tmp+sz1?1:0;
1734                 }
1735               else
1736                 {//case of SEG2 and SEG3
1737                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1738                     return 1;
1739                   if(!cm.isQuadratic())
1740                     {
1741                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1742                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1743                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1744                         return 2;
1745                       return 0;
1746                     }
1747                   else
1748                     {
1749                       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])
1750                         return 2;
1751                       return 0;
1752                     }
1753                 }
1754             }
1755           else
1756             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1757         }
1758     }
1759   return 0;
1760 }
1761
1762 /*!
1763  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1764  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1765  * and result remains unchanged.
1766  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1767  * If in 'candidates' pool -1 value is considered as an empty value.
1768  * WARNING this method returns only ONE set of result !
1769  */
1770 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1771 {
1772   if(candidates.size()<1)
1773     return false;
1774   bool ret=false;
1775   std::vector<int>::const_iterator iter=candidates.begin();
1776   int start=(*iter++);
1777   for(;iter!=candidates.end();iter++)
1778     {
1779       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1780       if(status!=0)
1781         {
1782           if(!ret)
1783             {
1784               result->pushBackSilent(start);
1785               ret=true;
1786             }
1787           if(status==1)
1788             result->pushBackSilent(*iter);
1789           else
1790             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1791         }
1792     }
1793   return ret;
1794 }
1795
1796 /*!
1797  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1798  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
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] commonCells
1808  * \param [out] commonCellsI
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   MEDCouplingAutoRefCountObjectPtr<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   MEDCouplingAutoRefCountObjectPtr<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 other->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   MEDCouplingAutoRefCountObjectPtr<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   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1937   arr=o2n->substr(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 arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1952  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1953  */
1954 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1955 {
1956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1957   DataArrayInt *commonCells=0,*commonCellsI=0;
1958   int thisNbCells=getNumberOfCells();
1959   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1961   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1962   int otherNbCells=other->getNumberOfCells();
1963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1964   arr2->alloc(otherNbCells,1);
1965   arr2->fillWithZero();
1966   int *arr2Ptr=arr2->getPointer();
1967   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1968   for(int i=0;i<nbOfCommon;i++)
1969     {
1970       int start=commonCellsPtr[commonCellsIPtr[i]];
1971       if(start<thisNbCells)
1972         {
1973           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1974             {
1975               int sig=commonCellsPtr[j]>0?1:-1;
1976               int val=std::abs(commonCellsPtr[j])-1;
1977               if(val>=thisNbCells)
1978                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1979             }
1980         }
1981     }
1982   arr2->setName(other->getName());
1983   if(arr2->presenceOfValue(0))
1984     return false;
1985   arr=arr2.retn();
1986   return true;
1987 }
1988
1989 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1990 {
1991   if(!other)
1992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1993   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1994   if(!otherC)
1995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1996   std::vector<const MEDCouplingUMesh *> ms(2);
1997   ms[0]=this;
1998   ms[1]=otherC;
1999   return MergeUMeshesOnSameCoords(ms);
2000 }
2001
2002 /*!
2003  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2004  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2005  * cellIds is not given explicitely but by a range python like.
2006  * 
2007  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2008  * \return a newly allocated
2009  * 
2010  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2011  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2012  */
2013 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2014 {
2015   if(getMeshDimension()!=-1)
2016     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2017   else
2018     {
2019       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2020       if(newNbOfCells!=1)
2021         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2022       if(start!=0)
2023         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2024       incrRef();
2025       return const_cast<MEDCouplingUMesh *>(this);
2026     }
2027 }
2028
2029 /*!
2030  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2031  * The result mesh shares or not the node coordinates array with \a this mesh depending
2032  * on \a keepCoords parameter.
2033  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2034  *           to write this mesh to the MED file, its cells must be sorted using
2035  *           sortCellsInMEDFileFrmt().
2036  *  \param [in] begin - an array of cell ids to include to the new mesh.
2037  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2038  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2039  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2040  *         by calling zipCoords().
2041  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2042  *         to delete this mesh using decrRef() as it is no more needed. 
2043  *  \throw If the coordinates array is not set.
2044  *  \throw If the nodal connectivity of cells is not defined.
2045  *  \throw If any cell id in the array \a begin is not valid.
2046  *
2047  *  \if ENABLE_EXAMPLES
2048  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2049  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2050  *  \endif
2051  */
2052 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2053 {
2054   if(getMeshDimension()!=-1)
2055     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2056   else
2057     {
2058       if(end-begin!=1)
2059         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2060       if(begin[0]!=0)
2061         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2062       incrRef();
2063       return const_cast<MEDCouplingUMesh *>(this);
2064     }
2065 }
2066
2067 /*!
2068  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2069  *
2070  * 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.
2071  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2072  * The number of cells of \b this will remain the same with this method.
2073  *
2074  * \param [in] begin begin of cell ids (included) of cells in this to assign
2075  * \param [in] end end of cell ids (excluded) of cells in this to assign
2076  * \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 ).
2077  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2078  */
2079 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2080 {
2081   checkConnectivityFullyDefined();
2082   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2083   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2085   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2086     {
2087       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2088       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2089       throw INTERP_KERNEL::Exception(oss.str().c_str());
2090     }
2091   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2092   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2093     {
2094       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2095       throw INTERP_KERNEL::Exception(oss.str().c_str());
2096     }
2097   int nbOfCells=getNumberOfCells();
2098   bool easyAssign=true;
2099   const int *connI=_nodal_connec_index->getConstPointer();
2100   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2101   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2102     {
2103       if(*it>=0 && *it<nbOfCells)
2104         {
2105           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2106         }
2107       else
2108         {
2109           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2110           throw INTERP_KERNEL::Exception(oss.str().c_str());
2111         }
2112     }
2113   if(easyAssign)
2114     {
2115       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2116       computeTypes();
2117     }
2118   else
2119     {
2120       DataArrayInt *arrOut=0,*arrIOut=0;
2121       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2122                                                arrOut,arrIOut);
2123       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2124       setConnectivity(arrOut,arrIOut,true);
2125     }
2126 }
2127
2128 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2129 {
2130   checkConnectivityFullyDefined();
2131   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2132   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2134   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2135     {
2136       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2137       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2138       throw INTERP_KERNEL::Exception(oss.str().c_str());
2139     }
2140   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2141   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2142     {
2143       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2144       throw INTERP_KERNEL::Exception(oss.str().c_str());
2145     }
2146   int nbOfCells=getNumberOfCells();
2147   bool easyAssign=true;
2148   const int *connI=_nodal_connec_index->getConstPointer();
2149   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2150   int it=start;
2151   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2152     {
2153       if(it>=0 && it<nbOfCells)
2154         {
2155           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2156         }
2157       else
2158         {
2159           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2160           throw INTERP_KERNEL::Exception(oss.str().c_str());
2161         }
2162     }
2163   if(easyAssign)
2164     {
2165       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2166       computeTypes();
2167     }
2168   else
2169     {
2170       DataArrayInt *arrOut=0,*arrIOut=0;
2171       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2172                                                 arrOut,arrIOut);
2173       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2174       setConnectivity(arrOut,arrIOut,true);
2175     }
2176 }                      
2177
2178 /*!
2179  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2180  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2181  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2182  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2183  *
2184  * \param [in] begin input start of array of node ids.
2185  * \param [in] end input end of array of node ids.
2186  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2187  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2188  */
2189 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2190 {
2191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2192   checkConnectivityFullyDefined();
2193   int tmp=-1;
2194   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2195   std::vector<bool> fastFinder(sz,false);
2196   for(const int *work=begin;work!=end;work++)
2197     if(*work>=0 && *work<sz)
2198       fastFinder[*work]=true;
2199   int nbOfCells=getNumberOfCells();
2200   const int *conn=getNodalConnectivity()->getConstPointer();
2201   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2202   for(int i=0;i<nbOfCells;i++)
2203     {
2204       int ref=0,nbOfHit=0;
2205       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2206         if(*work2>=0)
2207           {
2208             ref++;
2209             if(fastFinder[*work2])
2210               nbOfHit++;
2211           }
2212       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2213         cellIdsKept->pushBackSilent(i);
2214     }
2215   cellIdsKeptArr=cellIdsKept.retn();
2216 }
2217
2218 /*!
2219  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2220  * this->getMeshDimension(), that bound some cells of \a this mesh.
2221  * The cells of lower dimension to include to the result mesh are selected basing on
2222  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2223  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2224  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2225  * created mesh shares the node coordinates array with \a this mesh. 
2226  *  \param [in] begin - the array of node ids.
2227  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2228  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2229  *         array \a begin are added, else cells whose any node is in the
2230  *         array \a begin are added.
2231  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2232  *         to delete this mesh using decrRef() as it is no more needed. 
2233  *  \throw If the coordinates array is not set.
2234  *  \throw If the nodal connectivity of cells is not defined.
2235  *  \throw If any node id in \a begin is not valid.
2236  *
2237  *  \if ENABLE_EXAMPLES
2238  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2239  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2240  *  \endif
2241  */
2242 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2243 {
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2245   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2246   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2247   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2248   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2249 }
2250
2251 /*!
2252  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2253  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2254  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2255  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2256  *         by calling zipCoords().
2257  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2258  *         to delete this mesh using decrRef() as it is no more needed. 
2259  *  \throw If the coordinates array is not set.
2260  *  \throw If the nodal connectivity of cells is not defined.
2261  *
2262  *  \if ENABLE_EXAMPLES
2263  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2264  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2265  *  \endif
2266  */
2267 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2268 {
2269   DataArrayInt *desc=DataArrayInt::New();
2270   DataArrayInt *descIndx=DataArrayInt::New();
2271   DataArrayInt *revDesc=DataArrayInt::New();
2272   DataArrayInt *revDescIndx=DataArrayInt::New();
2273   //
2274   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2275   revDesc->decrRef();
2276   desc->decrRef();
2277   descIndx->decrRef();
2278   int nbOfCells=meshDM1->getNumberOfCells();
2279   const int *revDescIndxC=revDescIndx->getConstPointer();
2280   std::vector<int> boundaryCells;
2281   for(int i=0;i<nbOfCells;i++)
2282     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2283       boundaryCells.push_back(i);
2284   revDescIndx->decrRef();
2285   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2286   return ret;
2287 }
2288
2289 /*!
2290  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2291  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2292  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2293  */
2294 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2295 {
2296   checkFullyDefined();
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2301   //
2302   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2303   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2304   //
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2307   const int *revDescPtr=revDesc->getConstPointer();
2308   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2309   int nbOfCells=getNumberOfCells();
2310   std::vector<bool> ret1(nbOfCells,false);
2311   int sz=0;
2312   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2313     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2314       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2315   //
2316   DataArrayInt *ret2=DataArrayInt::New();
2317   ret2->alloc(sz,1);
2318   int *ret2Ptr=ret2->getPointer();
2319   sz=0;
2320   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2321     if(*it)
2322       *ret2Ptr++=sz;
2323   ret2->setName("BoundaryCells");
2324   return ret2;
2325 }
2326
2327 /*!
2328  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2329  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2330  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2331  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2332  *
2333  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2334  * This method method returns cells ids set s = s1 + s2 where :
2335  * 
2336  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2337  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2338  *
2339  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2341  *
2342  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2343  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2344  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2345  */
2346 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2347 {
2348   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2350   checkConnectivityFullyDefined();
2351   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2352   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2358   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2359   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2360   DataArrayInt *idsOtherInConsti=0;
2361   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2363   if(!b)
2364     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2365   std::set<int> s1;
2366   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2367     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2370   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2371   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2373   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2374   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2375   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2376   neighThisPartAuto=0;
2377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2378   const int li[2]={0,1};
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2380   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2382   s_renum1->sort();
2383   //
2384   cellIdsRk0=s0arr.retn();
2385   cellIdsRk1=s_renum1.retn();
2386 }
2387
2388 /*!
2389  * 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
2390  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2391  * 
2392  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2393  */
2394 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2395 {
2396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2400   //
2401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2402   revDesc=0; desc=0; descIndx=0;
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2405   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2406 }
2407
2408 /*!
2409  * Finds nodes lying on the boundary of \a this mesh.
2410  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2411  *          nodes. The caller is to delete this array using decrRef() as it is no
2412  *          more needed.
2413  *  \throw If the coordinates array is not set.
2414  *  \throw If the nodal connectivity of cells is node defined.
2415  *
2416  *  \if ENABLE_EXAMPLES
2417  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2418  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2419  *  \endif
2420  */
2421 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2422 {
2423   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2424   return skin->computeFetchedNodeIds();
2425 }
2426
2427 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2428 {
2429   incrRef();
2430   return const_cast<MEDCouplingUMesh *>(this);
2431 }
2432
2433 /*!
2434  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2435  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2436  * 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.
2437  * 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.
2438  * 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.
2439  *
2440  * \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
2441  *             parameter is altered during the call.
2442  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2443  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2444  * \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.
2445  *
2446  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2447  */
2448 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2449                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2450 {
2451   checkFullyDefined();
2452   otherDimM1OnSameCoords.checkFullyDefined();
2453   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2455   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2456     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2457   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2458   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2461   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2466   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2467   //
2468   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2470   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2471   DataArrayInt *idsTmp=0;
2472   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2474   if(!b)
2475     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2476   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2477   DataArrayInt *tmp0=0,*tmp1=0;
2478   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2481   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2483   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2484   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2485   //
2486   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2487   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2488   nodeIdsToDuplicate=s3.retn();
2489 }
2490
2491 /*!
2492  * This method operates a modification of the connectivity and coords in \b this.
2493  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2494  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2495  * 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
2496  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2497  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2498  * 
2499  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2500  * 
2501  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2502  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2503  */
2504 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2505 {
2506   int nbOfNodes=getNumberOfNodes();
2507   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2508   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2509 }
2510
2511 /*!
2512  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2513  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2514  *
2515  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2516  *
2517  * \sa renumberNodesInConn
2518  */
2519 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2520 {
2521   checkConnectivityFullyDefined();
2522   int *conn(getNodalConnectivity()->getPointer());
2523   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2524   int nbOfCells(getNumberOfCells());
2525   for(int i=0;i<nbOfCells;i++)
2526     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2527       {
2528         int& node=conn[iconn];
2529         if(node>=0)//avoid polyhedron separator
2530           {
2531             node+=offset;
2532           }
2533       }
2534   _nodal_connec->declareAsNew();
2535   updateTime();
2536 }
2537
2538 /*!
2539  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2540  *  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
2541  *  of a big mesh.
2542  */
2543 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2544 {
2545   checkConnectivityFullyDefined();
2546   int *conn(getNodalConnectivity()->getPointer());
2547   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2548   int nbOfCells(getNumberOfCells());
2549   for(int i=0;i<nbOfCells;i++)
2550     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2551       {
2552         int& node=conn[iconn];
2553         if(node>=0)//avoid polyhedron separator
2554           {
2555             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2556             if(it!=newNodeNumbersO2N.end())
2557               {
2558                 node=(*it).second;
2559               }
2560             else
2561               {
2562                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2563                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2564               }
2565           }
2566       }
2567   _nodal_connec->declareAsNew();
2568   updateTime();
2569 }
2570
2571 /*!
2572  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2573  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2574  * This method is a generalization of shiftNodeNumbersInConn().
2575  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2576  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2577  *         this->getNumberOfNodes(), in "Old to New" mode. 
2578  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2579  *  \throw If the nodal connectivity of cells is not defined.
2580  *
2581  *  \if ENABLE_EXAMPLES
2582  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2583  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2584  *  \endif
2585  */
2586 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2587 {
2588   checkConnectivityFullyDefined();
2589   int *conn=getNodalConnectivity()->getPointer();
2590   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2591   int nbOfCells(getNumberOfCells());
2592   for(int i=0;i<nbOfCells;i++)
2593     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2594       {
2595         int& node=conn[iconn];
2596         if(node>=0)//avoid polyhedron separator
2597           {
2598             node=newNodeNumbersO2N[node];
2599           }
2600       }
2601   _nodal_connec->declareAsNew();
2602   updateTime();
2603 }
2604
2605 /*!
2606  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2607  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2608  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2609  * 
2610  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2611  */
2612 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2613 {
2614   checkConnectivityFullyDefined();
2615   int *conn=getNodalConnectivity()->getPointer();
2616   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2617   int nbOfCells=getNumberOfCells();
2618   for(int i=0;i<nbOfCells;i++)
2619     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2620       {
2621         int& node=conn[iconn];
2622         if(node>=0)//avoid polyhedron separator
2623           {
2624             node+=delta;
2625           }
2626       }
2627   _nodal_connec->declareAsNew();
2628   updateTime();
2629 }
2630
2631 /*!
2632  * This method operates a modification of the connectivity in \b this.
2633  * 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.
2634  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2635  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2636  * 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
2637  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2638  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2639  * 
2640  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2641  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2642  * 
2643  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2644  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2645  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2646  */
2647 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2648 {
2649   checkConnectivityFullyDefined();
2650   std::map<int,int> m;
2651   int val=offset;
2652   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2653     m[*work]=val;
2654   int *conn=getNodalConnectivity()->getPointer();
2655   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2656   int nbOfCells=getNumberOfCells();
2657   for(int i=0;i<nbOfCells;i++)
2658     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2659       {
2660         int& node=conn[iconn];
2661         if(node>=0)//avoid polyhedron separator
2662           {
2663             std::map<int,int>::iterator it=m.find(node);
2664             if(it!=m.end())
2665               node=(*it).second;
2666           }
2667       }
2668   updateTime();
2669 }
2670
2671 /*!
2672  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2673  *
2674  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2675  * After the call of this method the number of cells remains the same as before.
2676  *
2677  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2678  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2679  * be strictly in [0;this->getNumberOfCells()).
2680  *
2681  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2682  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2683  * should be contained in[0;this->getNumberOfCells()).
2684  * 
2685  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2686  */
2687 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2688 {
2689   checkConnectivityFullyDefined();
2690   int nbCells=getNumberOfCells();
2691   const int *array=old2NewBg;
2692   if(check)
2693     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2694   //
2695   const int *conn=_nodal_connec->getConstPointer();
2696   const int *connI=_nodal_connec_index->getConstPointer();
2697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2698   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2699   const int *n2oPtr=n2o->begin();
2700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2701   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2702   newConn->copyStringInfoFrom(*_nodal_connec);
2703   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2704   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2705   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2706   //
2707   int *newC=newConn->getPointer();
2708   int *newCI=newConnI->getPointer();
2709   int loc=0;
2710   newCI[0]=loc;
2711   for(int i=0;i<nbCells;i++)
2712     {
2713       int pos=n2oPtr[i];
2714       int nbOfElts=connI[pos+1]-connI[pos];
2715       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2716       loc+=nbOfElts;
2717       newCI[i+1]=loc;
2718     }
2719   //
2720   setConnectivity(newConn,newConnI);
2721   if(check)
2722     free(const_cast<int *>(array));
2723 }
2724
2725 /*!
2726  * Finds cells whose bounding boxes intersect a given bounding box.
2727  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2728  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2729  *         zMax (if in 3D). 
2730  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2731  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2732  *         extent of the bounding box of cell to produce an addition to this bounding box.
2733  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2734  *         cells. The caller is to delete this array using decrRef() as it is no more
2735  *         needed. 
2736  *  \throw If the coordinates array is not set.
2737  *  \throw If the nodal connectivity of cells is not defined.
2738  *
2739  *  \if ENABLE_EXAMPLES
2740  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2741  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2742  *  \endif
2743  */
2744 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2745 {
2746   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2747   if(getMeshDimension()==-1)
2748     {
2749       elems->pushBackSilent(0);
2750       return elems.retn();
2751     }
2752   int dim=getSpaceDimension();
2753   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2754   const int* conn      = getNodalConnectivity()->getConstPointer();
2755   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2756   const double* coords = getCoords()->getConstPointer();
2757   int nbOfCells=getNumberOfCells();
2758   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2759     {
2760       for (int i=0; i<dim; i++)
2761         {
2762           elem_bb[i*2]=std::numeric_limits<double>::max();
2763           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2764         }
2765
2766       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2767         {
2768           int node= conn[inode];
2769           if(node>=0)//avoid polyhedron separator
2770             {
2771               for (int idim=0; idim<dim; idim++)
2772                 {
2773                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2774                     {
2775                       elem_bb[idim*2] = coords[node*dim+idim] ;
2776                     }
2777                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2778                     {
2779                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2780                     }
2781                 }
2782             }
2783         }
2784       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2785         elems->pushBackSilent(ielem);
2786     }
2787   return elems.retn();
2788 }
2789
2790 /*!
2791  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2792  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2793  * added in 'elems' parameter.
2794  */
2795 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2796 {
2797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2798   if(getMeshDimension()==-1)
2799     {
2800       elems->pushBackSilent(0);
2801       return elems.retn();
2802     }
2803   int dim=getSpaceDimension();
2804   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2805   const int* conn      = getNodalConnectivity()->getConstPointer();
2806   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2807   const double* coords = getCoords()->getConstPointer();
2808   int nbOfCells=getNumberOfCells();
2809   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2810     {
2811       for (int i=0; i<dim; i++)
2812         {
2813           elem_bb[i*2]=std::numeric_limits<double>::max();
2814           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2815         }
2816
2817       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2818         {
2819           int node= conn[inode];
2820           if(node>=0)//avoid polyhedron separator
2821             {
2822               for (int idim=0; idim<dim; idim++)
2823                 {
2824                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2825                     {
2826                       elem_bb[idim*2] = coords[node*dim+idim] ;
2827                     }
2828                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2829                     {
2830                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2831                     }
2832                 }
2833             }
2834         }
2835       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2836         elems->pushBackSilent(ielem);
2837     }
2838   return elems.retn();
2839 }
2840
2841 /*!
2842  * Returns a type of a cell by its id.
2843  *  \param [in] cellId - the id of the cell of interest.
2844  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2845  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2846  */
2847 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2848 {
2849   const int *ptI=_nodal_connec_index->getConstPointer();
2850   const int *pt=_nodal_connec->getConstPointer();
2851   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2852     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2853   else
2854     {
2855       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2856       throw INTERP_KERNEL::Exception(oss.str().c_str());
2857     }
2858 }
2859
2860 /*!
2861  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2862  * This method does not throw exception if geometric type \a type is not in \a this.
2863  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2864  * The coordinates array is not considered here.
2865  *
2866  * \param [in] type the geometric type
2867  * \return cell ids in this having geometric type \a type.
2868  */
2869 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2870 {
2871
2872   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2873   ret->alloc(0,1);
2874   checkConnectivityFullyDefined();
2875   int nbCells=getNumberOfCells();
2876   int mdim=getMeshDimension();
2877   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2878   if(mdim!=(int)cm.getDimension())
2879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2880   const int *ptI=_nodal_connec_index->getConstPointer();
2881   const int *pt=_nodal_connec->getConstPointer();
2882   for(int i=0;i<nbCells;i++)
2883     {
2884       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2885         ret->pushBackSilent(i);
2886     }
2887   return ret.retn();
2888 }
2889
2890 /*!
2891  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2892  */
2893 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2894 {
2895   const int *ptI=_nodal_connec_index->getConstPointer();
2896   const int *pt=_nodal_connec->getConstPointer();
2897   int nbOfCells=getNumberOfCells();
2898   int ret=0;
2899   for(int i=0;i<nbOfCells;i++)
2900     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2901       ret++;
2902   return ret;
2903 }
2904
2905 /*!
2906  * Returns the nodal connectivity of a given cell.
2907  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2908  * all returned node ids can be used in getCoordinatesOfNode().
2909  *  \param [in] cellId - an id of the cell of interest.
2910  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2911  *         cleared before the appending.
2912  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2913  */
2914 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2915 {
2916   const int *ptI=_nodal_connec_index->getConstPointer();
2917   const int *pt=_nodal_connec->getConstPointer();
2918   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2919     if(*w>=0)
2920       conn.push_back(*w);
2921 }
2922
2923 std::string MEDCouplingUMesh::simpleRepr() const
2924 {
2925   static const char msg0[]="No coordinates specified !";
2926   std::ostringstream ret;
2927   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2928   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2929   int tmpp1,tmpp2;
2930   double tt=getTime(tmpp1,tmpp2);
2931   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2932   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2933   if(_mesh_dim>=-1)
2934     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2935   else
2936     { ret << " Mesh dimension has not been set or is invalid !"; }
2937   if(_coords!=0)
2938     {
2939       const int spaceDim=getSpaceDimension();
2940       ret << spaceDim << "\nInfo attached on space dimension : ";
2941       for(int i=0;i<spaceDim;i++)
2942         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2943       ret << "\n";
2944     }
2945   else
2946     ret << msg0 << "\n";
2947   ret << "Number of nodes : ";
2948   if(_coords!=0)
2949     ret << getNumberOfNodes() << "\n";
2950   else
2951     ret << msg0 << "\n";
2952   ret << "Number of cells : ";
2953   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2954     ret << getNumberOfCells() << "\n";
2955   else
2956     ret << "No connectivity specified !" << "\n";
2957   ret << "Cell types present : ";
2958   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2959     {
2960       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2961       ret << cm.getRepr() << " ";
2962     }
2963   ret << "\n";
2964   return ret.str();
2965 }
2966
2967 std::string MEDCouplingUMesh::advancedRepr() const
2968 {
2969   std::ostringstream ret;
2970   ret << simpleRepr();
2971   ret << "\nCoordinates array : \n___________________\n\n";
2972   if(_coords)
2973     _coords->reprWithoutNameStream(ret);
2974   else
2975     ret << "No array set !\n";
2976   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2977   reprConnectivityOfThisLL(ret);
2978   return ret.str();
2979 }
2980
2981 /*!
2982  * This method returns a C++ code that is a dump of \a this.
2983  * This method will throw if this is not fully defined.
2984  */
2985 std::string MEDCouplingUMesh::cppRepr() const
2986 {
2987   static const char coordsName[]="coords";
2988   static const char connName[]="conn";
2989   static const char connIName[]="connI";
2990   checkFullyDefined();
2991   std::ostringstream ret; ret << "// coordinates" << std::endl;
2992   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2993   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2994   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2995   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2996   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2997   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2998   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2999   return ret.str();
3000 }
3001
3002 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3003 {
3004   std::ostringstream ret;
3005   reprConnectivityOfThisLL(ret);
3006   return ret.str();
3007 }
3008
3009 /*!
3010  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3011  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3012  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3013  * some algos).
3014  * 
3015  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3016  * 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
3017  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3018  */
3019 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3020 {
3021   int mdim=getMeshDimension();
3022   if(mdim<0)
3023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3024   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3026   bool needToCpyCT=true;
3027   if(!_nodal_connec)
3028     {
3029       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3030       needToCpyCT=false;
3031     }
3032   else
3033     {
3034       tmp1=_nodal_connec;
3035       tmp1->incrRef();
3036     }
3037   if(!_nodal_connec_index)
3038     {
3039       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3040       needToCpyCT=false;
3041     }
3042   else
3043     {
3044       tmp2=_nodal_connec_index;
3045       tmp2->incrRef();
3046     }
3047   ret->setConnectivity(tmp1,tmp2,false);
3048   if(needToCpyCT)
3049     ret->_types=_types;
3050   if(!_coords)
3051     {
3052       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3053       ret->setCoords(coords);
3054     }
3055   else
3056     ret->setCoords(_coords);
3057   return ret.retn();
3058 }
3059
3060 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3061 {
3062   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3063     {
3064       int nbOfCells=getNumberOfCells();
3065       const int *c=_nodal_connec->getConstPointer();
3066       const int *ci=_nodal_connec_index->getConstPointer();
3067       for(int i=0;i<nbOfCells;i++)
3068         {
3069           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3070           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3071           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3072           stream << "\n";
3073         }
3074     }
3075   else
3076     stream << "Connectivity not defined !\n";
3077 }
3078
3079 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3080 {
3081   const int *ptI=_nodal_connec_index->getConstPointer();
3082   const int *pt=_nodal_connec->getConstPointer();
3083   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3084     return ptI[cellId+1]-ptI[cellId]-1;
3085   else
3086     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3087 }
3088
3089 /*!
3090  * Returns types of cells of the specified part of \a this mesh.
3091  * This method avoids computing sub-mesh explicitely to get its types.
3092  *  \param [in] begin - an array of cell ids of interest.
3093  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3094  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3095  *         describing the cell types. 
3096  *  \throw If the coordinates array is not set.
3097  *  \throw If the nodal connectivity of cells is not defined.
3098  *  \sa getAllGeoTypes()
3099  */
3100 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3101 {
3102   checkFullyDefined();
3103   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3104   const int *conn=_nodal_connec->getConstPointer();
3105   const int *connIndex=_nodal_connec_index->getConstPointer();
3106   for(const int *w=begin;w!=end;w++)
3107     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3108   return ret;
3109 }
3110
3111 /*!
3112  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3113  * a set of types of cells constituting \a this mesh. 
3114  * This method is for advanced users having prepared their connectivity before. For
3115  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3116  *  \param [in] conn - the nodal connectivity array. 
3117  *  \param [in] connIndex - the nodal connectivity index array.
3118  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3119  *         mesh is updated.
3120  */
3121 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3122 {
3123   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3124   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3125   if(isComputingTypes)
3126     computeTypes();
3127   declareAsNew();
3128 }
3129
3130 /*!
3131  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3132  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3133  */
3134 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3135     _nodal_connec(0),_nodal_connec_index(0),
3136     _types(other._types)
3137 {
3138   if(other._nodal_connec)
3139     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3140   if(other._nodal_connec_index)
3141     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3142 }
3143
3144 MEDCouplingUMesh::~MEDCouplingUMesh()
3145 {
3146   if(_nodal_connec)
3147     _nodal_connec->decrRef();
3148   if(_nodal_connec_index)
3149     _nodal_connec_index->decrRef();
3150 }
3151
3152 /*!
3153  * Recomputes a set of cell types of \a this mesh. For more info see
3154  * \ref MEDCouplingUMeshNodalConnectivity.
3155  */
3156 void MEDCouplingUMesh::computeTypes()
3157 {
3158   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3159 }
3160
3161 /*!
3162  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3163  */
3164 void MEDCouplingUMesh::checkFullyDefined() const
3165 {
3166   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3167     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3168 }
3169
3170 /*!
3171  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3172  */
3173 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3174 {
3175   if(!_nodal_connec_index || !_nodal_connec)
3176     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3177 }
3178
3179 /*!
3180  * Returns a number of cells constituting \a this mesh. 
3181  *  \return int - the number of cells in \a this mesh.
3182  *  \throw If the nodal connectivity of cells is not defined.
3183  */
3184 int MEDCouplingUMesh::getNumberOfCells() const
3185
3186   if(_nodal_connec_index)
3187     return _nodal_connec_index->getNumberOfTuples()-1;
3188   else
3189     if(_mesh_dim==-1)
3190       return 1;
3191     else
3192       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3193 }
3194
3195 /*!
3196  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3197  * mesh. For more info see \ref MEDCouplingMeshesPage.
3198  *  \return int - the dimension of \a this mesh.
3199  *  \throw If the mesh dimension is not defined using setMeshDimension().
3200  */
3201 int MEDCouplingUMesh::getMeshDimension() const
3202 {
3203   if(_mesh_dim<-1)
3204     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3205   return _mesh_dim;
3206 }
3207
3208 /*!
3209  * Returns a length of the nodal connectivity array.
3210  * This method is for test reason. Normally the integer returned is not useable by
3211  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3212  *  \return int - the length of the nodal connectivity array.
3213  */
3214 int MEDCouplingUMesh::getMeshLength() const
3215 {
3216   return _nodal_connec->getNbOfElems();
3217 }
3218
3219 /*!
3220  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3221  */
3222 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3223 {
3224   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3225   tinyInfo.push_back(getMeshDimension());
3226   tinyInfo.push_back(getNumberOfCells());
3227   if(_nodal_connec)
3228     tinyInfo.push_back(getMeshLength());
3229   else
3230     tinyInfo.push_back(-1);
3231 }
3232
3233 /*!
3234  * First step of unserialization process.
3235  */
3236 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3237 {
3238   return tinyInfo[6]<=0;
3239 }
3240
3241 /*!
3242  * Second step of serialization process.
3243  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3244  */
3245 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3246 {
3247   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3248   if(tinyInfo[5]!=-1)
3249     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3250 }
3251
3252 /*!
3253  * Third and final step of serialization process.
3254  */
3255 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3256 {
3257   MEDCouplingPointSet::serialize(a1,a2);
3258   if(getMeshDimension()>-1)
3259     {
3260       a1=DataArrayInt::New();
3261       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3262       int *ptA1=a1->getPointer();
3263       const int *conn=getNodalConnectivity()->getConstPointer();
3264       const int *index=getNodalConnectivityIndex()->getConstPointer();
3265       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3266       std::copy(conn,conn+getMeshLength(),ptA1);
3267     }
3268   else
3269     a1=0;
3270 }
3271
3272 /*!
3273  * Second and final unserialization process.
3274  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3275  */
3276 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3277 {
3278   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3279   setMeshDimension(tinyInfo[5]);
3280   if(tinyInfo[7]!=-1)
3281     {
3282       // Connectivity
3283       const int *recvBuffer=a1->getConstPointer();
3284       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3285       myConnecIndex->alloc(tinyInfo[6]+1,1);
3286       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3287       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3288       myConnec->alloc(tinyInfo[7],1);
3289       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3290       setConnectivity(myConnec, myConnecIndex);
3291     }
3292 }
3293
3294 /*!
3295  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3296  * CellIds are given using range specified by a start an end and step.
3297  */
3298 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3299 {
3300   checkFullyDefined();
3301   int ncell=getNumberOfCells();
3302   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3303   ret->_mesh_dim=_mesh_dim;
3304   ret->setCoords(_coords);
3305   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3307   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3308   int work=start;
3309   const int *conn=_nodal_connec->getConstPointer();
3310   const int *connIndex=_nodal_connec_index->getConstPointer();
3311   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3312     {
3313       if(work>=0 && work<ncell)
3314         {
3315           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3316         }
3317       else
3318         {
3319           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3320           throw INTERP_KERNEL::Exception(oss.str().c_str());
3321         }
3322     }
3323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3324   int *newConnPtr=newConn->getPointer();
3325   std::set<INTERP_KERNEL::NormalizedCellType> types;
3326   work=start;
3327   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3328     {
3329       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3330       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3331     }
3332   ret->setConnectivity(newConn,newConnI,false);
3333   ret->_types=types;
3334   ret->copyTinyInfoFrom(this);
3335   return ret.retn();
3336 }
3337
3338 /*!
3339  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3340  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3341  * The return newly allocated mesh will share the same coordinates as \a this.
3342  */
3343 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3344 {
3345   checkConnectivityFullyDefined();
3346   int ncell=getNumberOfCells();
3347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3348   ret->_mesh_dim=_mesh_dim;
3349   ret->setCoords(_coords);
3350   std::size_t nbOfElemsRet=std::distance(begin,end);
3351   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3352   connIndexRet[0]=0;
3353   const int *conn=_nodal_connec->getConstPointer();
3354   const int *connIndex=_nodal_connec_index->getConstPointer();
3355   int newNbring=0;
3356   for(const int *work=begin;work!=end;work++,newNbring++)
3357     {
3358       if(*work>=0 && *work<ncell)
3359         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3360       else
3361         {
3362           free(connIndexRet);
3363           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3364           throw INTERP_KERNEL::Exception(oss.str().c_str());
3365         }
3366     }
3367   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3368   int *connRetWork=connRet;
3369   std::set<INTERP_KERNEL::NormalizedCellType> types;
3370   for(const int *work=begin;work!=end;work++)
3371     {
3372       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3373       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3374     }
3375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3376   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3378   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3379   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3380   ret->_types=types;
3381   ret->copyTinyInfoFrom(this);
3382   return ret.retn();
3383 }
3384
3385 /*!
3386  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3387  * mesh.<br>
3388  * For 1D cells, the returned field contains lengths.<br>
3389  * For 2D cells, the returned field contains areas.<br>
3390  * For 3D cells, the returned field contains volumes.
3391  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3392  *         orientation, i.e. the volume is always positive.
3393  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3394  *         and one time . The caller is to delete this field using decrRef() as it is no
3395  *         more needed.
3396  */
3397 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3398 {
3399   std::string name="MeasureOfMesh_";
3400   name+=getName();
3401   int nbelem=getNumberOfCells();
3402   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3403   field->setName(name);
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3405   array->alloc(nbelem,1);
3406   double *area_vol=array->getPointer();
3407   field->setArray(array) ; array=0;
3408   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3409   field->synchronizeTimeWithMesh();
3410   if(getMeshDimension()!=-1)
3411     {
3412       int ipt;
3413       INTERP_KERNEL::NormalizedCellType type;
3414       int dim_space=getSpaceDimension();
3415       const double *coords=getCoords()->getConstPointer();
3416       const int *connec=getNodalConnectivity()->getConstPointer();
3417       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3418       for(int iel=0;iel<nbelem;iel++)
3419         {
3420           ipt=connec_index[iel];
3421           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3422           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);
3423         }
3424       if(isAbs)
3425         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3426     }
3427   else
3428     {
3429       area_vol[0]=std::numeric_limits<double>::max();
3430     }
3431   return field.retn();
3432 }
3433
3434 /*!
3435  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3436  * mesh.<br>
3437  * For 1D cells, the returned array contains lengths.<br>
3438  * For 2D cells, the returned array contains areas.<br>
3439  * For 3D cells, the returned array contains volumes.
3440  * This method avoids building explicitly a part of \a this mesh to perform the work.
3441  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3442  *         orientation, i.e. the volume is always positive.
3443  *  \param [in] begin - an array of cell ids of interest.
3444  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3445  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3446  *          delete this array using decrRef() as it is no more needed.
3447  * 
3448  *  \if ENABLE_EXAMPLES
3449  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3450  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3451  *  \endif
3452  *  \sa getMeasureField()
3453  */
3454 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3455 {
3456   std::string name="PartMeasureOfMesh_";
3457   name+=getName();
3458   int nbelem=(int)std::distance(begin,end);
3459   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3460   array->setName(name);
3461   array->alloc(nbelem,1);
3462   double *area_vol=array->getPointer();
3463   if(getMeshDimension()!=-1)
3464     {
3465       int ipt;
3466       INTERP_KERNEL::NormalizedCellType type;
3467       int dim_space=getSpaceDimension();
3468       const double *coords=getCoords()->getConstPointer();
3469       const int *connec=getNodalConnectivity()->getConstPointer();
3470       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3471       for(const int *iel=begin;iel!=end;iel++)
3472         {
3473           ipt=connec_index[*iel];
3474           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3475           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3476         }
3477       if(isAbs)
3478         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3479     }
3480   else
3481     {
3482       area_vol[0]=std::numeric_limits<double>::max();
3483     }
3484   return array.retn();
3485 }
3486
3487 /*!
3488  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3489  * \a this one. The returned field contains the dual cell volume for each corresponding
3490  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3491  *  the dual mesh in P1 sens of \a this.<br>
3492  * For 1D cells, the returned field contains lengths.<br>
3493  * For 2D cells, the returned field contains areas.<br>
3494  * For 3D cells, the returned field contains volumes.
3495  * This method is useful to check "P1*" conservative interpolators.
3496  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3497  *         orientation, i.e. the volume is always positive.
3498  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499  *          nodes and one time. The caller is to delete this array using decrRef() as
3500  *          it is no more needed.
3501  */
3502 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3503 {
3504   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3505   std::string name="MeasureOnNodeOfMesh_";
3506   name+=getName();
3507   int nbNodes=getNumberOfNodes();
3508   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3509   double cst=1./((double)getMeshDimension()+1.);
3510   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3511   array->alloc(nbNodes,1);
3512   double *valsToFill=array->getPointer();
3513   std::fill(valsToFill,valsToFill+nbNodes,0.);
3514   const double *values=tmp->getArray()->getConstPointer();
3515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3517   getReverseNodalConnectivity(da,daInd);
3518   const int *daPtr=da->getConstPointer();
3519   const int *daIPtr=daInd->getConstPointer();
3520   for(int i=0;i<nbNodes;i++)
3521     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3522       valsToFill[i]+=cst*values[*cell];
3523   ret->setMesh(this);
3524   ret->setArray(array);
3525   return ret.retn();
3526 }
3527
3528 /*!
3529  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3530  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3531  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3532  * and are normalized.
3533  * <br> \a this can be either 
3534  * - a  2D mesh in 2D or 3D space or 
3535  * - an 1D mesh in 2D space.
3536  * 
3537  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3538  *          cells and one time. The caller is to delete this field using decrRef() as
3539  *          it is no more needed.
3540  *  \throw If the nodal connectivity of cells is not defined.
3541  *  \throw If the coordinates array is not set.
3542  *  \throw If the mesh dimension is not set.
3543  *  \throw If the mesh and space dimension is not as specified above.
3544  */
3545 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3546 {
3547   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3548     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3549   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3550   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3551   int nbOfCells=getNumberOfCells();
3552   int nbComp=getMeshDimension()+1;
3553   array->alloc(nbOfCells,nbComp);
3554   double *vals=array->getPointer();
3555   const int *connI=_nodal_connec_index->getConstPointer();
3556   const int *conn=_nodal_connec->getConstPointer();
3557   const double *coords=_coords->getConstPointer();
3558   if(getMeshDimension()==2)
3559     {
3560       if(getSpaceDimension()==3)
3561         {
3562           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3563           const double *locPtr=loc->getConstPointer();
3564           for(int i=0;i<nbOfCells;i++,vals+=3)
3565             {
3566               int offset=connI[i];
3567               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3568               double n=INTERP_KERNEL::norm<3>(vals);
3569               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3570             }
3571         }
3572       else
3573         {
3574           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3575           const double *isAbsPtr=isAbs->getArray()->begin();
3576           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3577             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3578         }
3579     }
3580   else//meshdimension==1
3581     {
3582       double tmp[2];
3583       for(int i=0;i<nbOfCells;i++)
3584         {
3585           int offset=connI[i];
3586           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3587           double n=INTERP_KERNEL::norm<2>(tmp);
3588           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3589           *vals++=-tmp[1];
3590           *vals++=tmp[0];
3591         }
3592     }
3593   ret->setArray(array);
3594   ret->setMesh(this);
3595   ret->synchronizeTimeWithSupport();
3596   return ret.retn();
3597 }
3598
3599 /*!
3600  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3601  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3602  * and are normalized.
3603  * <br> \a this can be either 
3604  * - a  2D mesh in 2D or 3D space or 
3605  * - an 1D mesh in 2D space.
3606  * 
3607  * This method avoids building explicitly a part of \a this mesh to perform the work.
3608  *  \param [in] begin - an array of cell ids of interest.
3609  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3610  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3611  *          cells and one time. The caller is to delete this field using decrRef() as
3612  *          it is no more needed.
3613  *  \throw If the nodal connectivity of cells is not defined.
3614  *  \throw If the coordinates array is not set.
3615  *  \throw If the mesh dimension is not set.
3616  *  \throw If the mesh and space dimension is not as specified above.
3617  *  \sa buildOrthogonalField()
3618  *
3619  *  \if ENABLE_EXAMPLES
3620  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3621  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3622  *  \endif
3623  */
3624 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3625 {
3626   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3627     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3628   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3629   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3630   std::size_t nbelems=std::distance(begin,end);
3631   int nbComp=getMeshDimension()+1;
3632   array->alloc((int)nbelems,nbComp);
3633   double *vals=array->getPointer();
3634   const int *connI=_nodal_connec_index->getConstPointer();
3635   const int *conn=_nodal_connec->getConstPointer();
3636   const double *coords=_coords->getConstPointer();
3637   if(getMeshDimension()==2)
3638     {
3639       if(getSpaceDimension()==3)
3640         {
3641           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3642           const double *locPtr=loc->getConstPointer();
3643           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3644             {
3645               int offset=connI[*i];
3646               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3647               double n=INTERP_KERNEL::norm<3>(vals);
3648               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3649             }
3650         }
3651       else
3652         {
3653           for(std::size_t i=0;i<nbelems;i++)
3654             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3655         }
3656     }
3657   else//meshdimension==1
3658     {
3659       double tmp[2];
3660       for(const int *i=begin;i!=end;i++)
3661         {
3662           int offset=connI[*i];
3663           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3664           double n=INTERP_KERNEL::norm<2>(tmp);
3665           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3666           *vals++=-tmp[1];
3667           *vals++=tmp[0];
3668         }
3669     }
3670   ret->setArray(array);
3671   ret->setMesh(this);
3672   ret->synchronizeTimeWithSupport();
3673   return ret.retn();
3674 }
3675
3676 /*!
3677  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3678  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3679  * and are \b not normalized.
3680  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3681  *          cells and one time. The caller is to delete this field using decrRef() as
3682  *          it is no more needed.
3683  *  \throw If the nodal connectivity of cells is not defined.
3684  *  \throw If the coordinates array is not set.
3685  *  \throw If \a this->getMeshDimension() != 1.
3686  *  \throw If \a this mesh includes cells of type other than SEG2.
3687  */
3688 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3689 {
3690   if(getMeshDimension()!=1)
3691     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3692   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3693     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3694   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3695   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3696   int nbOfCells=getNumberOfCells();
3697   int spaceDim=getSpaceDimension();
3698   array->alloc(nbOfCells,spaceDim);
3699   double *pt=array->getPointer();
3700   const double *coo=getCoords()->getConstPointer();
3701   std::vector<int> conn;
3702   conn.reserve(2);
3703   for(int i=0;i<nbOfCells;i++)
3704     {
3705       conn.resize(0);
3706       getNodeIdsOfCell(i,conn);
3707       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3708     }
3709   ret->setArray(array);
3710   ret->setMesh(this);
3711   ret->synchronizeTimeWithSupport();
3712   return ret.retn();
3713 }
3714
3715 /*!
3716  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3717  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3718  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3719  * from. If a result face is shared by two 3D cells, then the face in included twice in
3720  * the result mesh.
3721  *  \param [in] origin - 3 components of a point defining location of the plane.
3722  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3723  *         must be greater than 1e-6.
3724  *  \param [in] eps - half-thickness of the plane.
3725  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3726  *         producing correspondent 2D cells. The caller is to delete this array
3727  *         using decrRef() as it is no more needed.
3728  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3729  *         not share the node coordinates array with \a this mesh. The caller is to
3730  *         delete this mesh using decrRef() as it is no more needed.  
3731  *  \throw If the coordinates array is not set.
3732  *  \throw If the nodal connectivity of cells is not defined.
3733  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3734  *  \throw If magnitude of \a vec is less than 1e-6.
3735  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3736  *  \throw If \a this includes quadratic cells.
3737  */
3738 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3739 {
3740   checkFullyDefined();
3741   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3744   if(candidates->empty())
3745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3746   std::vector<int> nodes;
3747   DataArrayInt *cellIds1D=0;
3748   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3749   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3754   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3755   revDesc2=0; revDescIndx2=0;
3756   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3757   revDesc1=0; revDescIndx1=0;
3758   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3760   //
3761   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3762   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3763     cut3DCurve[*it]=-1;
3764   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3765   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3766   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3767                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3768                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3770   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3771   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3772   if(cellIds2->empty())
3773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3774   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3775   ret->setCoords(mDesc1->getCoords());
3776   ret->setConnectivity(conn,connI,true);
3777   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3778   return ret.retn();
3779 }
3780
3781 /*!
3782  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3783 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
3784 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3785 the result mesh.
3786  *  \param [in] origin - 3 components of a point defining location of the plane.
3787  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3788  *         must be greater than 1e-6.
3789  *  \param [in] eps - half-thickness of the plane.
3790  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3791  *         producing correspondent segments. The caller is to delete this array
3792  *         using decrRef() as it is no more needed.
3793  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3794  *         mesh in 3D space. This mesh does not share the node coordinates array with
3795  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3796  *         no more needed. 
3797  *  \throw If the coordinates array is not set.
3798  *  \throw If the nodal connectivity of cells is not defined.
3799  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3800  *  \throw If magnitude of \a vec is less than 1e-6.
3801  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3802  *  \throw If \a this includes quadratic cells.
3803  */
3804 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3805 {
3806   checkFullyDefined();
3807   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3808     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3810   if(candidates->empty())
3811     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3812   std::vector<int> nodes;
3813   DataArrayInt *cellIds1D=0;
3814   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3815   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3820   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3821   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3823   //
3824   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3825   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3826     cut3DCurve[*it]=-1;
3827   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3828   int ncellsSub=subMesh->getNumberOfCells();
3829   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3830   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3831                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3832                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3834   conn->alloc(0,1);
3835   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3836   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3837   for(int i=0;i<ncellsSub;i++)
3838     {
3839       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3840         {
3841           if(cut3DSurf[i].first!=-2)
3842             {
3843               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3844               connI->pushBackSilent(conn->getNumberOfTuples());
3845               cellIds2->pushBackSilent(i);
3846             }
3847           else
3848             {
3849               int cellId3DSurf=cut3DSurf[i].second;
3850               int offset=nodalI[cellId3DSurf]+1;
3851               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3852               for(int j=0;j<nbOfEdges;j++)
3853                 {
3854                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3855                   connI->pushBackSilent(conn->getNumberOfTuples());
3856                   cellIds2->pushBackSilent(cellId3DSurf);
3857                 }
3858             }
3859         }
3860     }
3861   if(cellIds2->empty())
3862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3863   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3864   ret->setCoords(mDesc1->getCoords());
3865   ret->setConnectivity(conn,connI,true);
3866   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3867   return ret.retn();
3868 }
3869
3870 /*!
3871  * Finds cells whose bounding boxes intersect a given plane.
3872  *  \param [in] origin - 3 components of a point defining location of the plane.
3873  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3874  *         must be greater than 1e-6.
3875  *  \param [in] eps - half-thickness of the plane.
3876  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3877  *         cells. The caller is to delete this array using decrRef() as it is no more
3878  *         needed.
3879  *  \throw If the coordinates array is not set.
3880  *  \throw If the nodal connectivity of cells is not defined.
3881  *  \throw If \a this->getSpaceDimension() != 3.
3882  *  \throw If magnitude of \a vec is less than 1e-6.
3883  *  \sa buildSlice3D()
3884  */
3885 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3886 {
3887   checkFullyDefined();
3888   if(getSpaceDimension()!=3)
3889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3890   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3891   if(normm<1e-6)
3892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3893   double vec2[3];
3894   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3895   double angle=acos(vec[2]/normm);
3896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3897   double bbox[6];
3898   if(angle>eps)
3899     {
3900       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3901       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3902       if(normm2/normm>1e-6)
3903         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3904       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3905       mw->setCoords(coo);
3906       mw->getBoundingBox(bbox);
3907       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3908       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3909     }
3910   else
3911     {
3912       getBoundingBox(bbox);
3913       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3914       cellIds=getCellsInBoundingBox(bbox,eps);
3915     }
3916   return cellIds.retn();
3917 }
3918
3919 /*!
3920  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3921  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3922  * No consideration of coordinate is done by this method.
3923  * 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)
3924  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3925  */
3926 bool MEDCouplingUMesh::isContiguous1D() const
3927 {
3928   if(getMeshDimension()!=1)
3929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3930   int nbCells=getNumberOfCells();
3931   if(nbCells<1)
3932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3933   const int *connI=_nodal_connec_index->getConstPointer();
3934   const int *conn=_nodal_connec->getConstPointer();
3935   int ref=conn[connI[0]+2];
3936   for(int i=1;i<nbCells;i++)
3937     {
3938       if(conn[connI[i]+1]!=ref)
3939         return false;
3940       ref=conn[connI[i]+2];
3941     }
3942   return true;
3943 }
3944
3945 /*!
3946  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3947  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3948  * \param pt reference point of the line
3949  * \param v normalized director vector of the line
3950  * \param eps max precision before throwing an exception
3951  * \param res output of size this->getNumberOfCells
3952  */
3953 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3954 {
3955   if(getMeshDimension()!=1)
3956     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3957   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3958     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3959   if(getSpaceDimension()!=3)
3960     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3961   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3962   const double *fPtr=f->getArray()->getConstPointer();
3963   double tmp[3];
3964   for(int i=0;i<getNumberOfCells();i++)
3965     {
3966       const double *tmp1=fPtr+3*i;
3967       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3968       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3969       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3970       double n1=INTERP_KERNEL::norm<3>(tmp);
3971       n1/=INTERP_KERNEL::norm<3>(tmp1);
3972       if(n1>eps)
3973         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3974     }
3975   const double *coo=getCoords()->getConstPointer();
3976   for(int i=0;i<getNumberOfNodes();i++)
3977     {
3978       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3979       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3980       res[i]=std::accumulate(tmp,tmp+3,0.);
3981     }
3982 }
3983
3984 /*!
3985  * 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. 
3986  * \a this is expected to be a mesh so that its space dimension is equal to its
3987  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3988  * 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).
3989  *
3990  * 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
3991  * 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).
3992  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3993  *
3994  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3995  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3996  *
3997  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3998  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3999  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4000  * \return the positive value of the distance.
4001  * \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
4002  * dimension - 1.
4003  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4004  */
4005 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4006 {
4007   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4008   if(meshDim!=spaceDim-1)
4009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4010   if(meshDim!=2 && meshDim!=1)
4011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4012   checkFullyDefined();
4013   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4014     { 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()); }
4015   DataArrayInt *ret1=0;
4016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4019   cellId=*ret1Safe->begin();
4020   return *ret0->begin();
4021 }
4022
4023 /*!
4024  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4025  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4026  * 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
4027  * 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).
4028  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4029  * 
4030  * \a this is expected to be a mesh so that its space dimension is equal to its
4031  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4032  * 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).
4033  *
4034  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4035  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036  *
4037  * \param [in] pts the list of points in which each tuple represents a point
4038  * \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.
4039  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4040  * \throw if number of components of \a pts is not equal to the space dimension.
4041  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4042  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4043  */
4044 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4045 {
4046   if(!pts)
4047     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4048   pts->checkAllocated();
4049   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4050   if(meshDim!=spaceDim-1)
4051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4052   if(meshDim!=2 && meshDim!=1)
4053     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4054   if(pts->getNumberOfComponents()!=spaceDim)
4055     {
4056       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4057       throw INTERP_KERNEL::Exception(oss.str().c_str());
4058     }
4059   checkFullyDefined();
4060   int nbCells=getNumberOfCells();
4061   if(nbCells==0)
4062     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4063   int nbOfPts=pts->getNumberOfTuples();
4064   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4066   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4067   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4068   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4069   const double *bbox(bboxArr->begin());
4070   switch(spaceDim)
4071   {
4072     case 3:
4073       {
4074         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4075         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4076           {
4077             double x=std::numeric_limits<double>::max();
4078             std::vector<int> elems;
4079             myTree.getMinDistanceOfMax(ptsPtr,x);
4080             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4081             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4082           }
4083         break;
4084       }
4085     case 2:
4086       {
4087         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4088         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4089           {
4090             double x=std::numeric_limits<double>::max();
4091             std::vector<int> elems;
4092             myTree.getMinDistanceOfMax(ptsPtr,x);
4093             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4094             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4095           }
4096         break;
4097       }
4098     default:
4099       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4100   }
4101   cellIds=ret1.retn();
4102   return ret0.retn();
4103 }
4104
4105 /*!
4106  * \param [in] pt the start pointer (included) of the coordinates of the point
4107  * \param [in] cellIdsBg the start pointer (included) of cellIds
4108  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4109  * \param [in] nc nodal connectivity
4110  * \param [in] ncI nodal connectivity index
4111  * \param [in,out] ret0 the min distance between \a this and the external input point
4112  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4113  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4114  */
4115 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)
4116 {
4117   cellId=-1;
4118   ret0=std::numeric_limits<double>::max();
4119   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4120     {
4121       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4122       {
4123         case INTERP_KERNEL::NORM_TRI3:
4124           {
4125             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4126             if(tmp<ret0)
4127               { ret0=tmp; cellId=*zeCell; }
4128             break;
4129           }
4130         case INTERP_KERNEL::NORM_QUAD4:
4131         case INTERP_KERNEL::NORM_POLYGON:
4132           {
4133             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4134             if(tmp<ret0)
4135               { ret0=tmp; cellId=*zeCell; }
4136             break;
4137           }
4138         default:
4139           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4140       }
4141     }
4142 }
4143
4144 /*!
4145  * \param [in] pt the start pointer (included) of the coordinates of the point
4146  * \param [in] cellIdsBg the start pointer (included) of cellIds
4147  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4148  * \param [in] nc nodal connectivity
4149  * \param [in] ncI nodal connectivity index
4150  * \param [in,out] ret0 the min distance between \a this and the external input point
4151  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4152  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4153  */
4154 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)
4155 {
4156   cellId=-1;
4157   ret0=std::numeric_limits<double>::max();
4158   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4159     {
4160       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4161       {
4162         case INTERP_KERNEL::NORM_SEG2:
4163           {
4164             std::size_t uselessEntry=0;
4165             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4166             tmp=sqrt(tmp);
4167             if(tmp<ret0)
4168               { ret0=tmp; cellId=*zeCell; }
4169             break;
4170           }
4171         default:
4172           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4173       }
4174     }
4175 }
4176
4177 /*!
4178  * Finds cells in contact with a ball (i.e. a point with precision). 
4179  * 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.
4180  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4181  *
4182  * \warning This method is suitable if the caller intends to evaluate only one
4183  *          point, for more points getCellsContainingPoints() is recommended as it is
4184  *          faster. 
4185  *  \param [in] pos - array of coordinates of the ball central point.
4186  *  \param [in] eps - ball radius.
4187  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4188  *         if there are no such cells.
4189  *  \throw If the coordinates array is not set.
4190  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4191  */
4192 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4193 {
4194   std::vector<int> elts;
4195   getCellsContainingPoint(pos,eps,elts);
4196   if(elts.empty())
4197     return -1;
4198   return elts.front();
4199 }
4200
4201 /*!
4202  * Finds cells in contact with a ball (i.e. a point with precision).
4203  * 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.
4204  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4205  * \warning This method is suitable if the caller intends to evaluate only one
4206  *          point, for more points getCellsContainingPoints() is recommended as it is
4207  *          faster. 
4208  *  \param [in] pos - array of coordinates of the ball central point.
4209  *  \param [in] eps - ball radius.
4210  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4211  *         before inserting ids.
4212  *  \throw If the coordinates array is not set.
4213  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4214  *
4215  *  \if ENABLE_EXAMPLES
4216  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4217  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4218  *  \endif
4219  */
4220 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4221 {
4222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4223   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4224   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4225 }
4226
4227 /// @cond INTERNAL
4228
4229 namespace ParaMEDMEM
4230 {
4231   template<const int SPACEDIMM>
4232   class DummyClsMCUG
4233   {
4234   public:
4235     static const int MY_SPACEDIM=SPACEDIMM;
4236     static const int MY_MESHDIM=8;
4237     typedef int MyConnType;
4238     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4239     // begin
4240     // useless, but for windows compilation ...
4241     const double* getCoordinatesPtr() const { return 0; }
4242     const int* getConnectivityPtr() const { return 0; }
4243     const int* getConnectivityIndexPtr() const { return 0; }
4244     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4245     // end
4246   };
4247
4248   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4249   {
4250     INTERP_KERNEL::Edge *ret(0);
4251     MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4252     m[n0]=bg[0]; m[n1]=bg[1];
4253     switch(typ)
4254     {
4255       case INTERP_KERNEL::NORM_SEG2:
4256         {
4257           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4258           break;
4259         }
4260       case INTERP_KERNEL::NORM_SEG3:
4261         {
4262           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4263           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4264           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4265           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4266           bool colinearity(inters.areColinears());
4267           delete e1; delete e2;
4268           if(colinearity)
4269             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4270           else
4271             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4272           break;
4273         }
4274       default:
4275         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4276     }
4277     return ret;
4278   }
4279
4280   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4281   {
4282     INTERP_KERNEL::Edge *ret=0;
4283     switch(typ)
4284     {
4285       case INTERP_KERNEL::NORM_SEG2:
4286         {
4287           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4288           break;
4289         }
4290       case INTERP_KERNEL::NORM_SEG3:
4291         {
4292           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4293           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4294           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4295           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4296           bool colinearity=inters.areColinears();
4297           delete e1; delete e2;
4298           if(colinearity)
4299             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4300           else
4301             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4302           mapp2[bg[2]].second=false;
4303           break;
4304         }
4305       default:
4306         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4307     }
4308     return ret;
4309   }
4310
4311   /*!
4312    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4313    * the global mesh 'mDesc'.
4314    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4315    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4316    */
4317   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4318                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4319   {
4320     mapp.clear();
4321     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.
4322     const double *coo=mDesc->getCoords()->getConstPointer();
4323     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4324     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4325     std::set<int> s;
4326     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4327       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4328     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4329       {
4330         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4331         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4332       }
4333     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4334     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4335       {
4336         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4337         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4338       }
4339     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4340       {
4341         if((*it2).second.second)
4342           mapp[(*it2).second.first]=(*it2).first;
4343         ((*it2).second.first)->decrRef();
4344       }
4345     return ret;
4346   }
4347
4348   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4349   {
4350     if(nodeId>=offset2)
4351       {
4352         int locId=nodeId-offset2;
4353         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4354       }
4355     if(nodeId>=offset1)
4356       {
4357         int locId=nodeId-offset1;
4358         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4359       }
4360     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4361   }
4362
4363   /**
4364    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4365    */
4366   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4367                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4368                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4369   {
4370     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4371       {
4372         int eltId1=abs(*desc1)-1;
4373         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4374           {
4375             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4376             if(it==mappRev.end())
4377               {
4378                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4379                 mapp[node]=*it1;
4380                 mappRev[*it1]=node;
4381               }
4382           }
4383       }
4384   }
4385 }
4386
4387 /// @endcond
4388
4389 template<int SPACEDIM>
4390 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4391                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4392 {
4393   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4394   int *eltsIndexPtr(eltsIndex->getPointer());
4395   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4396   const double *bbox(bboxArr->begin());
4397   int nbOfCells=getNumberOfCells();
4398   const int *conn=_nodal_connec->getConstPointer();
4399   const int *connI=_nodal_connec_index->getConstPointer();
4400   double bb[2*SPACEDIM];
4401   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4402   for(int i=0;i<nbOfPoints;i++)
4403     {
4404       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4405       for(int j=0;j<SPACEDIM;j++)
4406         {
4407           bb[2*j]=pos[SPACEDIM*i+j];
4408           bb[2*j+1]=pos[SPACEDIM*i+j];
4409         }
4410       std::vector<int> candidates;
4411       myTree.getIntersectingElems(bb,candidates);
4412       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4413         {
4414           int sz(connI[(*iter)+1]-connI[*iter]-1);
4415           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4416           bool status(false);
4417           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4418             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4419           else
4420             {
4421               if(SPACEDIM!=2)
4422                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4423               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4424               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4425               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4426               INTERP_KERNEL::QuadraticPolygon *pol(0);
4427               for(int j=0;j<sz;j++)
4428                 {
4429                   int nodeId(conn[connI[*iter]+1+j]);
4430                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4431                 }
4432               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4433                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4434               else
4435                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4436               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4437               double a(0.),b(0.),c(0.);
4438               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4439               status=pol->isInOrOut2(n);
4440               delete pol; n->decrRef();
4441             }
4442           if(status)
4443             {
4444               eltsIndexPtr[i+1]++;
4445               elts->pushBackSilent(*iter);
4446             }
4447         }
4448     }
4449 }
4450 /*!
4451  * Finds cells in contact with several balls (i.e. points with precision).
4452  * This method is an extension of getCellContainingPoint() and
4453  * getCellsContainingPoint() for the case of multiple points.
4454  * 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.
4455  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4456  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4457  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4458  *         this->getSpaceDimension() * \a nbOfPoints 
4459  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4460  *  \param [in] eps - radius of balls (i.e. the precision).
4461  *  \param [out] elts - vector returning ids of found cells.
4462  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4463  *         dividing cell ids in \a elts into groups each referring to one
4464  *         point. Its every element (except the last one) is an index pointing to the
4465  *         first id of a group of cells. For example cells in contact with the *i*-th
4466  *         point are described by following range of indices:
4467  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4468  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4469  *         Number of cells in contact with the *i*-th point is
4470  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4471  *  \throw If the coordinates array is not set.
4472  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4473  *
4474  *  \if ENABLE_EXAMPLES
4475  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4476  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4477  *  \endif
4478  */
4479 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4480                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4481 {
4482   int spaceDim=getSpaceDimension();
4483   int mDim=getMeshDimension();
4484   if(spaceDim==3)
4485     {
4486       if(mDim==3)
4487         {
4488           const double *coords=_coords->getConstPointer();
4489           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4490         }
4491       /*else if(mDim==2)
4492         {
4493
4494         }*/
4495       else
4496         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4497     }
4498   else if(spaceDim==2)
4499     {
4500       if(mDim==2)
4501         {
4502           const double *coords=_coords->getConstPointer();
4503           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4504         }
4505       else
4506         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4507     }
4508   else if(spaceDim==1)
4509     {
4510       if(mDim==1)
4511         {
4512           const double *coords=_coords->getConstPointer();
4513           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4514         }
4515       else
4516         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4517     }
4518   else
4519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4520 }
4521
4522 /*!
4523  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4524  * least two its edges intersect each other anywhere except their extremities. An
4525  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4526  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4527  *         cleared before filling in.
4528  *  \param [in] eps - precision.
4529  *  \throw If \a this->getMeshDimension() != 2.
4530  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4531  */
4532 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4533 {
4534   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4535   if(getMeshDimension()!=2)
4536     throw INTERP_KERNEL::Exception(msg);
4537   int spaceDim=getSpaceDimension();
4538   if(spaceDim!=2 && spaceDim!=3)
4539     throw INTERP_KERNEL::Exception(msg);
4540   const int *conn=_nodal_connec->getConstPointer();
4541   const int *connI=_nodal_connec_index->getConstPointer();
4542   int nbOfCells=getNumberOfCells();
4543   std::vector<double> cell2DinS2;
4544   for(int i=0;i<nbOfCells;i++)
4545     {
4546       int offset=connI[i];
4547       int nbOfNodesForCell=connI[i+1]-offset-1;
4548       if(nbOfNodesForCell<=3)
4549         continue;
4550       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4551       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4552       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4553         cells.push_back(i);
4554       cell2DinS2.clear();
4555     }
4556 }
4557
4558 /*!
4559  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4560  *
4561  * 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.
4562  * 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.
4563  * 
4564  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4565  * This convex envelop is computed using Jarvis march algorithm.
4566  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4567  * 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)
4568  * 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.
4569  *
4570  * \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.
4571  * \sa MEDCouplingUMesh::colinearize2D
4572  */
4573 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4574 {
4575   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4576     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4577   checkFullyDefined();
4578   const double *coords=getCoords()->getConstPointer();
4579   int nbOfCells=getNumberOfCells();
4580   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4581   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4583   int *workIndexOut=nodalConnecIndexOut->getPointer();
4584   *workIndexOut=0;
4585   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4586   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4587   std::set<INTERP_KERNEL::NormalizedCellType> types;
4588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4589   isChanged->alloc(0,1);
4590   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4591     {
4592       int pos=nodalConnecOut->getNumberOfTuples();
4593       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4594         isChanged->pushBackSilent(i);
4595       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4596       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4597     }
4598   if(isChanged->empty())
4599     return 0;
4600   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4601   _types=types;
4602   return isChanged.retn();
4603 }
4604
4605 /*!
4606  * This method is \b NOT const because it can modify \a this.
4607  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4608  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4609  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4610  * \b 1 for translation and rotation around point of 'mesh1D'.
4611  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4612  */
4613 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4614 {
4615   checkFullyDefined();
4616   mesh1D->checkFullyDefined();
4617   if(!mesh1D->isContiguous1D())
4618     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4619   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4620     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4621   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4622     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4623   if(mesh1D->getMeshDimension()!=1)
4624     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4625   bool isQuad=false;
4626   if(isPresenceOfQuadratic())
4627     {
4628       if(mesh1D->isFullyQuadratic())
4629         isQuad=true;
4630       else
4631         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4632     }
4633   int oldNbOfNodes(getNumberOfNodes());
4634   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4635   switch(policy)
4636   {
4637     case 0:
4638       {
4639         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4640         break;
4641       }
4642     case 1:
4643       {
4644         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4645         break;
4646       }
4647     default:
4648       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4649   }
4650   setCoords(newCoords);
4651   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4652   updateTime();
4653   return ret.retn();
4654 }
4655
4656 /*!
4657  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4658  * If it is not the case an exception will be thrown.
4659  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4660  * intersection of plane defined by ('origin','vec').
4661  * This method has one in/out parameter : 'cut3DCurve'.
4662  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4663  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4664  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4665  * This method will throw an exception if \a this contains a non linear segment.
4666  */
4667 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4668 {
4669   checkFullyDefined();
4670   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4672   int ncells=getNumberOfCells();
4673   int nnodes=getNumberOfNodes();
4674   double vec2[3],vec3[3],vec4[3];
4675   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4676   if(normm<1e-6)
4677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4678   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4679   const int *conn=_nodal_connec->getConstPointer();
4680   const int *connI=_nodal_connec_index->getConstPointer();
4681   const double *coo=_coords->getConstPointer();
4682   std::vector<double> addCoo;
4683   for(int i=0;i<ncells;i++)
4684     {
4685       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4686         {
4687           if(cut3DCurve[i]==-2)
4688             {
4689               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4690               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];
4691               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4692               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4693               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4694                 {
4695                   const double *st2=coo+3*st;
4696                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4697                   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]));
4698                   if(pos>eps && pos<1-eps)
4699                     {
4700                       int nNode=((int)addCoo.size())/3;
4701                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4702                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4703                       cut3DCurve[i]=nnodes+nNode;
4704                     }
4705                 }
4706             }
4707         }
4708       else
4709         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4710     }
4711   if(!addCoo.empty())
4712     {
4713       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4714       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4715       coo2->alloc(newNbOfNodes,3);
4716       double *tmp=coo2->getPointer();
4717       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4718       std::copy(addCoo.begin(),addCoo.end(),tmp);
4719       DataArrayDouble::SetArrayIn(coo2,_coords);
4720     }
4721 }
4722
4723 /*!
4724  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4725  * \param mesh1D is the input 1D mesh used for translation computation.
4726  * \return newCoords new coords filled by this method. 
4727  */
4728 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4729 {
4730   int oldNbOfNodes=getNumberOfNodes();
4731   int nbOf1DCells=mesh1D->getNumberOfCells();
4732   int spaceDim=getSpaceDimension();
4733   DataArrayDouble *ret=DataArrayDouble::New();
4734   std::vector<bool> isQuads;
4735   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4736   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4737   double *retPtr=ret->getPointer();
4738   const double *coords=getCoords()->getConstPointer();
4739   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4740   std::vector<int> v;
4741   std::vector<double> c;
4742   double vec[3];
4743   v.reserve(3);
4744   c.reserve(6);
4745   for(int i=0;i<nbOf1DCells;i++)
4746     {
4747       v.resize(0);
4748       mesh1D->getNodeIdsOfCell(i,v);
4749       c.resize(0);
4750       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4751       mesh1D->getCoordinatesOfNode(v[0],c);
4752       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4753       for(int j=0;j<oldNbOfNodes;j++)
4754         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4755       if(isQuad)
4756         {
4757           c.resize(0);
4758           mesh1D->getCoordinatesOfNode(v[1],c);
4759           mesh1D->getCoordinatesOfNode(v[0],c);
4760           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4761           for(int j=0;j<oldNbOfNodes;j++)
4762             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4763         }
4764     }
4765   ret->copyStringInfoFrom(*getCoords());
4766   return ret;
4767 }
4768
4769 /*!
4770  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4771  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4772  * \return newCoords new coords filled by this method. 
4773  */
4774 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4775 {
4776   if(mesh1D->getSpaceDimension()==2)
4777     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4778   if(mesh1D->getSpaceDimension()==3)
4779     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4780   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4781 }
4782
4783 /*!
4784  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4785  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4786  * \return newCoords new coords filled by this method. 
4787  */
4788 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4789 {
4790   if(isQuad)
4791     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4792   int oldNbOfNodes=getNumberOfNodes();
4793   int nbOf1DCells=mesh1D->getNumberOfCells();
4794   if(nbOf1DCells<2)
4795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4796   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4797   int nbOfLevsInVec=nbOf1DCells+1;
4798   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4799   double *retPtr=ret->getPointer();
4800   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4801   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4802   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4803   tmp->setCoords(tmp2);
4804   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4805   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4806   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4807   for(int i=1;i<nbOfLevsInVec;i++)
4808     {
4809       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4810       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4811       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4812       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4813       tmp->translate(vec);
4814       double tmp3[2],radius,alpha,alpha0;
4815       const double *p0=i+1<nbOfLevsInVec?begin:third;
4816       const double *p1=i+1<nbOfLevsInVec?end:begin;
4817       const double *p2=i+1<nbOfLevsInVec?third:end;
4818       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4819       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]);
4820       double angle=acos(cosangle/(radius*radius));
4821       tmp->rotate(end,0,angle);
4822       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4823     }
4824   return ret.retn();
4825 }
4826
4827 /*!
4828  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4829  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4830  * \return newCoords new coords filled by this method. 
4831  */
4832 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4833 {
4834   if(isQuad)
4835     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4836   int oldNbOfNodes=getNumberOfNodes();
4837   int nbOf1DCells=mesh1D->getNumberOfCells();
4838   if(nbOf1DCells<2)
4839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4840   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4841   int nbOfLevsInVec=nbOf1DCells+1;
4842   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4843   double *retPtr=ret->getPointer();
4844   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4845   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4846   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4847   tmp->setCoords(tmp2);
4848   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4849   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4850   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4851   for(int i=1;i<nbOfLevsInVec;i++)
4852     {
4853       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4854       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4855       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4856       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4857       tmp->translate(vec);
4858       double tmp3[2],radius,alpha,alpha0;
4859       const double *p0=i+1<nbOfLevsInVec?begin:third;
4860       const double *p1=i+1<nbOfLevsInVec?end:begin;
4861       const double *p2=i+1<nbOfLevsInVec?third:end;
4862       double vecPlane[3]={
4863         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4864         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4865         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4866       };
4867       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4868       if(norm>1.e-7)
4869         {
4870           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4871           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4872           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4873           double s2=norm2;
4874           double c2=cos(asin(s2));
4875           double m[3][3]={
4876             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4877             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4878             {-vec2[1]*s2, vec2[0]*s2, c2}
4879           };
4880           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]};
4881           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]};
4882           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]};
4883           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4884           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]);
4885           double angle=acos(cosangle/(radius*radius));
4886           tmp->rotate(end,vecPlane,angle);
4887         }
4888       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4889     }
4890   return ret.retn();
4891 }
4892
4893 /*!
4894  * This method is private because not easy to use for end user. This method is const contrary to
4895  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4896  * the coords sorted slice by slice.
4897  * \param isQuad specifies presence of quadratic cells.
4898  */
4899 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4900 {
4901   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4902   int nbOf2DCells(getNumberOfCells());
4903   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4904   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4905   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4907   newConnI->alloc(nbOf3DCells+1,1);
4908   int *newConnIPtr(newConnI->getPointer());
4909   *newConnIPtr++=0;
4910   std::vector<int> newc;
4911   for(int j=0;j<nbOf2DCells;j++)
4912     {
4913       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4914       *newConnIPtr++=(int)newc.size();
4915     }
4916   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4917   int *newConnPtr(newConn->getPointer());
4918   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4919   newConnIPtr=newConnI->getPointer();
4920   for(int iz=0;iz<nbOf1DCells;iz++)
4921     {
4922       if(iz!=0)
4923         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4924       const int *posOfTypeOfCell(newConnIPtr);
4925       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4926         {
4927           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4928           if(icell!=*posOfTypeOfCell)
4929             {
4930               if(*iter!=-1)
4931                 *newConnPtr=(*iter)+iz*deltaPerLev;
4932               else
4933                 *newConnPtr=-1;
4934             }
4935           else
4936             {
4937               *newConnPtr=*iter;
4938               posOfTypeOfCell++;
4939             }
4940         }
4941     }
4942   ret->setConnectivity(newConn,newConnI,true);
4943   ret->setCoords(getCoords());
4944   return ret;
4945 }
4946
4947 /*!
4948  * Checks if \a this mesh is constituted by only quadratic cells.
4949  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4950  *  \throw If the coordinates array is not set.
4951  *  \throw If the nodal connectivity of cells is not defined.
4952  */
4953 bool MEDCouplingUMesh::isFullyQuadratic() const
4954 {
4955   checkFullyDefined();
4956   bool ret=true;
4957   int nbOfCells=getNumberOfCells();
4958   for(int i=0;i<nbOfCells && ret;i++)
4959     {
4960       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4961       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4962       ret=cm.isQuadratic();
4963     }
4964   return ret;
4965 }
4966
4967 /*!
4968  * Checks if \a this mesh includes any quadratic cell.
4969  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4970  *  \throw If the coordinates array is not set.
4971  *  \throw If the nodal connectivity of cells is not defined.
4972  */
4973 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4974 {
4975   checkFullyDefined();
4976   bool ret=false;
4977   int nbOfCells=getNumberOfCells();
4978   for(int i=0;i<nbOfCells && !ret;i++)
4979     {
4980       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4981       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4982       ret=cm.isQuadratic();
4983     }
4984   return ret;
4985 }
4986
4987 /*!
4988  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4989  * this mesh, it remains unchanged.
4990  *  \throw If the coordinates array is not set.
4991  *  \throw If the nodal connectivity of cells is not defined.
4992  */
4993 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4994 {
4995   checkFullyDefined();
4996   int nbOfCells=getNumberOfCells();
4997   int delta=0;
4998   const int *iciptr=_nodal_connec_index->getConstPointer();
4999   for(int i=0;i<nbOfCells;i++)
5000     {
5001       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003       if(cm.isQuadratic())
5004         {
5005           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5006           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5007           if(!cml.isDynamic())
5008             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5009           else
5010             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5011         }
5012     }
5013   if(delta==0)
5014     return ;
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5017   const int *icptr=_nodal_connec->getConstPointer();
5018   newConn->alloc(getMeshLength()-delta,1);
5019   newConnI->alloc(nbOfCells+1,1);
5020   int *ocptr=newConn->getPointer();
5021   int *ociptr=newConnI->getPointer();
5022   *ociptr=0;
5023   _types.clear();
5024   for(int i=0;i<nbOfCells;i++,ociptr++)
5025     {
5026       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5027       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5028       if(!cm.isQuadratic())
5029         {
5030           _types.insert(type);
5031           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5032           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5033         }
5034       else
5035         {
5036           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5037           _types.insert(typel);
5038           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039           int newNbOfNodes=cml.getNumberOfNodes();
5040           if(cml.isDynamic())
5041             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5042           *ocptr++=(int)typel;
5043           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5044           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5045         }
5046     }
5047   setConnectivity(newConn,newConnI,false);
5048 }
5049
5050 /*!
5051  * This method converts all linear cell in \a this to quadratic one.
5052  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5053  * 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)
5054  * 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.
5055  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5056  * end of the existing coordinates.
5057  * 
5058  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5059  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5060  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5061  * 
5062  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5063  *
5064  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5065  */
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5067 {
5068   DataArrayInt *conn=0,*connI=0;
5069   DataArrayDouble *coords=0;
5070   std::set<INTERP_KERNEL::NormalizedCellType> types;
5071   checkFullyDefined();
5072   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5073   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5074   int meshDim=getMeshDimension();
5075   switch(conversionType)
5076   {
5077     case 0:
5078       switch(meshDim)
5079       {
5080         case 1:
5081           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5082           connSafe=conn; connISafe=connI; coordsSafe=coords;
5083           break;
5084         case 2:
5085           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5086           connSafe=conn; connISafe=connI; coordsSafe=coords;
5087           break;
5088         case 3:
5089           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5090           connSafe=conn; connISafe=connI; coordsSafe=coords;
5091           break;
5092         default:
5093           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5094       }
5095       break;
5096         case 1:
5097           {
5098             switch(meshDim)
5099             {
5100               case 1:
5101                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5102                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5103                 break;
5104               case 2:
5105                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5106                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5107                 break;
5108               case 3:
5109                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5110                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5111                 break;
5112               default:
5113                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5114             }
5115             break;
5116           }
5117         default:
5118           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5119   }
5120   setConnectivity(connSafe,connISafe,false);
5121   _types=types;
5122   setCoords(coordsSafe);
5123   return ret.retn();
5124 }
5125
5126 #if 0
5127 /*!
5128  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5129  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5130  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5131  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5132  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5133  * This method can be seen as the opposite method of colinearize2D.
5134  * 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
5135  * to avoid to modify the numbering of existing nodes.
5136  *
5137  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5138  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5139  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5140  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5141  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5142  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5143  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5144  *
5145  * \sa buildDescendingConnectivity2
5146  */
5147 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5148                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5149 {
5150   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5152   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5153   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5155   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5157   //DataArrayInt *out0(0),*outi0(0);
5158   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5159   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5160   //out0s=out0s->buildUnique(); out0s->sort(true);
5161 }
5162 #endif
5163
5164 /*!
5165  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5166  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5167  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5168  */
5169 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5170 {
5171   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5175   int nbOfCells=getNumberOfCells();
5176   int nbOfNodes=getNumberOfNodes();
5177   const int *cPtr=_nodal_connec->getConstPointer();
5178   const int *icPtr=_nodal_connec_index->getConstPointer();
5179   int lastVal=0,offset=nbOfNodes;
5180   for(int i=0;i<nbOfCells;i++,icPtr++)
5181     {
5182       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5183       if(type==INTERP_KERNEL::NORM_SEG2)
5184         {
5185           types.insert(INTERP_KERNEL::NORM_SEG3);
5186           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5187           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5188           newConn->pushBackSilent(offset++);
5189           lastVal+=4;
5190           newConnI->pushBackSilent(lastVal);
5191           ret->pushBackSilent(i);
5192         }
5193       else
5194         {
5195           types.insert(type);
5196           lastVal+=(icPtr[1]-icPtr[0]);
5197           newConnI->pushBackSilent(lastVal);
5198           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5199         }
5200     }
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5202   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5203   return ret.retn();
5204 }
5205
5206 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
5207 {
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5211   //
5212   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5213   DataArrayInt *conn1D=0,*conn1DI=0;
5214   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5215   DataArrayDouble *coordsTmp=0;
5216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5219   const int *c1DPtr=conn1D->begin();
5220   const int *c1DIPtr=conn1DI->begin();
5221   int nbOfCells=getNumberOfCells();
5222   const int *cPtr=_nodal_connec->getConstPointer();
5223   const int *icPtr=_nodal_connec_index->getConstPointer();
5224   int lastVal=0;
5225   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5226     {
5227       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5229       if(!cm.isQuadratic())
5230         {
5231           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5232           types.insert(typ2); newConn->pushBackSilent(typ2);
5233           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5234           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5235             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5236           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5237           newConnI->pushBackSilent(lastVal);
5238           ret->pushBackSilent(i);
5239         }
5240       else
5241         {
5242           types.insert(typ);
5243           lastVal+=(icPtr[1]-icPtr[0]);
5244           newConnI->pushBackSilent(lastVal);
5245           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5246         }
5247     }
5248   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5249   return ret.retn();
5250 }
5251
5252 /*!
5253  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256  */
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 {
5259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5260   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5261   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5262 }
5263
5264 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5265 {
5266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5268   //
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5272   //
5273   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5274   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5275   DataArrayInt *conn1D=0,*conn1DI=0;
5276   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5277   DataArrayDouble *coordsTmp=0;
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5281   const int *c1DPtr=conn1D->begin();
5282   const int *c1DIPtr=conn1DI->begin();
5283   int nbOfCells=getNumberOfCells();
5284   const int *cPtr=_nodal_connec->getConstPointer();
5285   const int *icPtr=_nodal_connec_index->getConstPointer();
5286   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5287   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5288     {
5289       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5290       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5291       if(!cm.isQuadratic())
5292         {
5293           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5294           types.insert(typ2); newConn->pushBackSilent(typ2);
5295           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5296           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5297             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5298           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5299           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5300           newConnI->pushBackSilent(lastVal);
5301           ret->pushBackSilent(i);
5302         }
5303       else
5304         {
5305           types.insert(typ);
5306           lastVal+=(icPtr[1]-icPtr[0]);
5307           newConnI->pushBackSilent(lastVal);
5308           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5309         }
5310     }
5311   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5312   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5313   return ret.retn();
5314 }
5315
5316 /*!
5317  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5318  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5319  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5320  */
5321 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5322 {
5323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5324   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5325   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5326 }
5327
5328 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5329 {
5330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5331   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5333   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5334   //
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5338   //
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5340   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5341   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5342   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5343   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5346   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5350   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5351   int nbOfCells=getNumberOfCells();
5352   const int *cPtr=_nodal_connec->getConstPointer();
5353   const int *icPtr=_nodal_connec_index->getConstPointer();
5354   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5355   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5356     {
5357       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5358       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5359       if(!cm.isQuadratic())
5360         {
5361           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5362           if(typ2==INTERP_KERNEL::NORM_ERROR)
5363             {
5364               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5365               throw INTERP_KERNEL::Exception(oss.str().c_str());
5366             }
5367           types.insert(typ2); newConn->pushBackSilent(typ2);
5368           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5369           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5370             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5371           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5372             {
5373               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5374               int tmpPos=newConn->getNumberOfTuples();
5375               newConn->pushBackSilent(nodeId2);
5376               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5377             }
5378           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5379           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5380           newConnI->pushBackSilent(lastVal);
5381           ret->pushBackSilent(i);
5382         }
5383       else
5384         {
5385           types.insert(typ);
5386           lastVal+=(icPtr[1]-icPtr[0]);
5387           newConnI->pushBackSilent(lastVal);
5388           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5389         }
5390     }
5391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5393   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5394   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5395   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5396   int *c=newConn->getPointer();
5397   const int *cI(newConnI->begin());
5398   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5399     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5400   offset=coordsTmp2Safe->getNumberOfTuples();
5401   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5402     c[cI[(*elt)+1]-1]+=offset;
5403   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5404   return ret.retn();
5405 }
5406
5407 /*!
5408  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5409  * so that the number of cells remains the same. Quadratic faces are converted to
5410  * polygons. This method works only for 2D meshes in
5411  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5412  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5413  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5414  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5415  *         a polylinized edge constituting the input polygon.
5416  *  \throw If the coordinates array is not set.
5417  *  \throw If the nodal connectivity of cells is not defined.
5418  *  \throw If \a this->getMeshDimension() != 2.
5419  *  \throw If \a this->getSpaceDimension() != 2.
5420  */
5421 void MEDCouplingUMesh::tessellate2D(double eps)
5422 {
5423   checkFullyDefined();
5424   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5426   double epsa=fabs(eps);
5427   if(epsa<std::numeric_limits<double>::min())
5428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5434   revDesc1=0; revDescIndx1=0;
5435   mDesc->tessellate2DCurve(eps);
5436   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5437   setCoords(mDesc->getCoords());
5438 }
5439
5440 /*!
5441  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5442  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5443  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5444  *         a sub-divided edge.
5445  *  \throw If the coordinates array is not set.
5446  *  \throw If the nodal connectivity of cells is not defined.
5447  *  \throw If \a this->getMeshDimension() != 1.
5448  *  \throw If \a this->getSpaceDimension() != 2.
5449  */
5450 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5451 {
5452   checkFullyDefined();
5453   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5455   double epsa=fabs(eps);
5456   if(epsa<std::numeric_limits<double>::min())
5457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5458   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5459   int nbCells=getNumberOfCells();
5460   int nbNodes=getNumberOfNodes();
5461   const int *conn=_nodal_connec->getConstPointer();
5462   const int *connI=_nodal_connec_index->getConstPointer();
5463   const double *coords=_coords->getConstPointer();
5464   std::vector<double> addCoo;
5465   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5467   newConnI->alloc(nbCells+1,1);
5468   int *newConnIPtr=newConnI->getPointer();
5469   *newConnIPtr=0;
5470   int tmp1[3];
5471   INTERP_KERNEL::Node *tmp2[3];
5472   std::set<INTERP_KERNEL::NormalizedCellType> types;
5473   for(int i=0;i<nbCells;i++,newConnIPtr++)
5474     {
5475       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5476       if(cm.isQuadratic())
5477         {//assert(connI[i+1]-connI[i]-1==3)
5478           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5479           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5480           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5481           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5482           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5483           if(eac)
5484             {
5485               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5486               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5487               delete eac;
5488               newConnIPtr[1]=(int)newConn.size();
5489             }
5490           else
5491             {
5492               types.insert(INTERP_KERNEL::NORM_SEG2);
5493               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5494               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5495               newConnIPtr[1]=newConnIPtr[0]+3;
5496             }
5497         }
5498       else
5499         {
5500           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5501           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5502           newConnIPtr[1]=newConnIPtr[0]+3;
5503         }
5504     }
5505   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5506     return ;
5507   _types=types;
5508   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5510   newConnArr->alloc((int)newConn.size(),1);
5511   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5512   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5513   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5514   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5515   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5516   std::copy(addCoo.begin(),addCoo.end(),work);
5517   DataArrayDouble::SetArrayIn(newCoords,_coords);
5518   updateTime();
5519 }
5520
5521 /*!
5522  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5523  * In addition, returns an array mapping new cells to old ones. <br>
5524  * This method typically increases the number of cells in \a this mesh
5525  * but the number of nodes remains \b unchanged.
5526  * That's why the 3D splitting policies
5527  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5528  *  \param [in] policy - specifies a pattern used for splitting.
5529  * The semantic of \a policy is:
5530  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5531  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5532  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5533  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5534  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5535  *          an id of old cell producing it. The caller is to delete this array using
5536  *         decrRef() as it is no more needed. 
5537  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5538  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5539  *          and \a this->getMeshDimension() != 3. 
5540  *  \throw If \a policy is not one of the four discussed above.
5541  *  \throw If the nodal connectivity of cells is not defined.
5542  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5543  */
5544 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5545 {
5546   switch(policy)
5547   {
5548     case 0:
5549       return simplexizePol0();
5550     case 1:
5551       return simplexizePol1();
5552     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5553         return simplexizePlanarFace5();
5554     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5555         return simplexizePlanarFace6();
5556     default:
5557       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)");
5558   }
5559 }
5560
5561 /*!
5562  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5563  * - 1D: INTERP_KERNEL::NORM_SEG2
5564  * - 2D: INTERP_KERNEL::NORM_TRI3
5565  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5566  *
5567  * This method is useful for users that need to use P1 field services as
5568  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5569  * All these methods need mesh support containing only simplex cells.
5570  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5571  *  \throw If the coordinates array is not set.
5572  *  \throw If the nodal connectivity of cells is not defined.
5573  *  \throw If \a this->getMeshDimension() < 1.
5574  */
5575 bool MEDCouplingUMesh::areOnlySimplexCells() const
5576 {
5577   checkFullyDefined();
5578   int mdim=getMeshDimension();
5579   if(mdim<1 || mdim>3)
5580     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5581   int nbCells=getNumberOfCells();
5582   const int *conn=_nodal_connec->getConstPointer();
5583   const int *connI=_nodal_connec_index->getConstPointer();
5584   for(int i=0;i<nbCells;i++)
5585     {
5586       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5587       if(!cm.isSimplex())
5588         return false;
5589     }
5590   return true;
5591 }
5592
5593 /*!
5594  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5595  */
5596 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5597 {
5598   checkConnectivityFullyDefined();
5599   if(getMeshDimension()!=2)
5600     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5601   int nbOfCells=getNumberOfCells();
5602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5603   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5604   ret->alloc(nbOfCells+nbOfCutCells,1);
5605   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5606   int *retPt=ret->getPointer();
5607   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5608   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5609   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5610   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5611   int *pt=newConn->getPointer();
5612   int *ptI=newConnI->getPointer();
5613   ptI[0]=0;
5614   const int *oldc=_nodal_connec->getConstPointer();
5615   const int *ci=_nodal_connec_index->getConstPointer();
5616   for(int i=0;i<nbOfCells;i++,ci++)
5617     {
5618       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5619         {
5620           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5621             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5622           pt=std::copy(tmp,tmp+8,pt);
5623           ptI[1]=ptI[0]+4;
5624           ptI[2]=ptI[0]+8;
5625           *retPt++=i;
5626           *retPt++=i;
5627           ptI+=2;
5628         }
5629       else
5630         {
5631           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5632           ptI[1]=ptI[0]+ci[1]-ci[0];
5633           ptI++;
5634           *retPt++=i;
5635         }
5636     }
5637   _nodal_connec->decrRef();
5638   _nodal_connec=newConn.retn();
5639   _nodal_connec_index->decrRef();
5640   _nodal_connec_index=newConnI.retn();
5641   computeTypes();
5642   updateTime();
5643   return ret.retn();
5644 }
5645
5646 /*!
5647  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5648  */
5649 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5650 {
5651   checkConnectivityFullyDefined();
5652   if(getMeshDimension()!=2)
5653     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5654   int nbOfCells=getNumberOfCells();
5655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5656   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5657   ret->alloc(nbOfCells+nbOfCutCells,1);
5658   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5659   int *retPt=ret->getPointer();
5660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5662   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5663   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5664   int *pt=newConn->getPointer();
5665   int *ptI=newConnI->getPointer();
5666   ptI[0]=0;
5667   const int *oldc=_nodal_connec->getConstPointer();
5668   const int *ci=_nodal_connec_index->getConstPointer();
5669   for(int i=0;i<nbOfCells;i++,ci++)
5670     {
5671       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5672         {
5673           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5674             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5675           pt=std::copy(tmp,tmp+8,pt);
5676           ptI[1]=ptI[0]+4;
5677           ptI[2]=ptI[0]+8;
5678           *retPt++=i;
5679           *retPt++=i;
5680           ptI+=2;
5681         }
5682       else
5683         {
5684           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5685           ptI[1]=ptI[0]+ci[1]-ci[0];
5686           ptI++;
5687           *retPt++=i;
5688         }
5689     }
5690   _nodal_connec->decrRef();
5691   _nodal_connec=newConn.retn();
5692   _nodal_connec_index->decrRef();
5693   _nodal_connec_index=newConnI.retn();
5694   computeTypes();
5695   updateTime();
5696   return ret.retn();
5697 }
5698
5699 /*!
5700  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5701  */
5702 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5703 {
5704   checkConnectivityFullyDefined();
5705   if(getMeshDimension()!=3)
5706     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5707   int nbOfCells=getNumberOfCells();
5708   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5709   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5710   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5711   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5712   int *retPt=ret->getPointer();
5713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5714   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5715   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5716   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5717   int *pt=newConn->getPointer();
5718   int *ptI=newConnI->getPointer();
5719   ptI[0]=0;
5720   const int *oldc=_nodal_connec->getConstPointer();
5721   const int *ci=_nodal_connec_index->getConstPointer();
5722   for(int i=0;i<nbOfCells;i++,ci++)
5723     {
5724       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5725         {
5726           for(int j=0;j<5;j++,pt+=5,ptI++)
5727             {
5728               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5729               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];
5730               *retPt++=i;
5731               ptI[1]=ptI[0]+5;
5732             }
5733         }
5734       else
5735         {
5736           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5737           ptI[1]=ptI[0]+ci[1]-ci[0];
5738           ptI++;
5739           *retPt++=i;
5740         }
5741     }
5742   _nodal_connec->decrRef();
5743   _nodal_connec=newConn.retn();
5744   _nodal_connec_index->decrRef();
5745   _nodal_connec_index=newConnI.retn();
5746   computeTypes();
5747   updateTime();
5748   return ret.retn();
5749 }
5750
5751 /*!
5752  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5753  */
5754 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5755 {
5756   checkConnectivityFullyDefined();
5757   if(getMeshDimension()!=3)
5758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5759   int nbOfCells=getNumberOfCells();
5760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5761   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5762   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5763   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5764   int *retPt=ret->getPointer();
5765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5766   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5767   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5768   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5769   int *pt=newConn->getPointer();
5770   int *ptI=newConnI->getPointer();
5771   ptI[0]=0;
5772   const int *oldc=_nodal_connec->getConstPointer();
5773   const int *ci=_nodal_connec_index->getConstPointer();
5774   for(int i=0;i<nbOfCells;i++,ci++)
5775     {
5776       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5777         {
5778           for(int j=0;j<6;j++,pt+=5,ptI++)
5779             {
5780               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5781               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];
5782               *retPt++=i;
5783               ptI[1]=ptI[0]+5;
5784             }
5785         }
5786       else
5787         {
5788           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5789           ptI[1]=ptI[0]+ci[1]-ci[0];
5790           ptI++;
5791           *retPt++=i;
5792         }
5793     }
5794   _nodal_connec->decrRef();
5795   _nodal_connec=newConn.retn();
5796   _nodal_connec_index->decrRef();
5797   _nodal_connec_index=newConnI.retn();
5798   computeTypes();
5799   updateTime();
5800   return ret.retn();
5801 }
5802
5803 /*!
5804  * 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.
5805  * This method completly ignore coordinates.
5806  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5807  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5808  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5809  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5810  */
5811 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5812 {
5813   checkFullyDefined();
5814   if(getMeshDimension()!=2)
5815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5816   int nbOfCells=getNumberOfCells();
5817   int *connI=_nodal_connec_index->getPointer();
5818   int newConnLgth=0;
5819   for(int i=0;i<nbOfCells;i++,connI++)
5820     {
5821       int offset=descIndex[i];
5822       int nbOfEdges=descIndex[i+1]-offset;
5823       //
5824       bool ddirect=desc[offset+nbOfEdges-1]>0;
5825       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5826       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5827       for(int j=0;j<nbOfEdges;j++)
5828         {
5829           bool direct=desc[offset+j]>0;
5830           int edgeId=std::abs(desc[offset+j])-1;
5831           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5832             {
5833               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5834               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5835               int ref2=direct?id1:id2;
5836               if(ref==ref2)
5837                 {
5838                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5839                   newConnLgth+=nbOfSubNodes-1;
5840                   ref=direct?id2:id1;
5841                 }
5842               else
5843                 {
5844                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5845                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5846                 }
5847             }
5848           else
5849             {
5850               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5851             }
5852         }
5853       newConnLgth++;//+1 is for cell type
5854       connI[1]=newConnLgth;
5855     }
5856   //
5857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5858   newConn->alloc(newConnLgth,1);
5859   int *work=newConn->getPointer();
5860   for(int i=0;i<nbOfCells;i++)
5861     {
5862       *work++=INTERP_KERNEL::NORM_POLYGON;
5863       int offset=descIndex[i];
5864       int nbOfEdges=descIndex[i+1]-offset;
5865       for(int j=0;j<nbOfEdges;j++)
5866         {
5867           bool direct=desc[offset+j]>0;
5868           int edgeId=std::abs(desc[offset+j])-1;
5869           if(direct)
5870             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5871           else
5872             {
5873               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5874               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5875               work=std::copy(it,it+nbOfSubNodes-1,work);
5876             }
5877         }
5878     }
5879   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5880   _types.clear();
5881   if(nbOfCells>0)
5882     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5883 }
5884
5885 /*!
5886  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5887  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5888  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5889  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5890  * so it can be useful to call mergeNodes() before calling this method.
5891  *  \throw If \a this->getMeshDimension() <= 1.
5892  *  \throw If the coordinates array is not set.
5893  *  \throw If the nodal connectivity of cells is not defined.
5894  */
5895 void MEDCouplingUMesh::convertDegeneratedCells()
5896 {
5897   checkFullyDefined();
5898   if(getMeshDimension()<=1)
5899     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5900   int nbOfCells=getNumberOfCells();
5901   if(nbOfCells<1)
5902     return ;
5903   int initMeshLgth=getMeshLength();
5904   int *conn=_nodal_connec->getPointer();
5905   int *index=_nodal_connec_index->getPointer();
5906   int posOfCurCell=0;
5907   int newPos=0;
5908   int lgthOfCurCell;
5909   for(int i=0;i<nbOfCells;i++)
5910     {
5911       lgthOfCurCell=index[i+1]-posOfCurCell;
5912       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5913       int newLgth;
5914       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5915                                                                                                      conn+newPos+1,newLgth);
5916       conn[newPos]=newType;
5917       newPos+=newLgth+1;
5918       posOfCurCell=index[i+1];
5919       index[i+1]=newPos;
5920     }
5921   if(newPos!=initMeshLgth)
5922     _nodal_connec->reAlloc(newPos);
5923   computeTypes();
5924 }
5925
5926 /*!
5927  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5928  * A cell is considered to be oriented correctly if an angle between its
5929  * normal vector and a given vector is less than \c PI / \c 2.
5930  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5931  *         cells. 
5932  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5933  *         checked.
5934  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5935  *         is not cleared before filling in.
5936  *  \throw If \a this->getMeshDimension() != 2.
5937  *  \throw If \a this->getSpaceDimension() != 3.
5938  *
5939  *  \if ENABLE_EXAMPLES
5940  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5941  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5942  *  \endif
5943  */
5944 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5945 {
5946   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5947     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5948   int nbOfCells=getNumberOfCells();
5949   const int *conn=_nodal_connec->getConstPointer();
5950   const int *connI=_nodal_connec_index->getConstPointer();
5951   const double *coordsPtr=_coords->getConstPointer();
5952   for(int i=0;i<nbOfCells;i++)
5953     {
5954       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5955       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5956         {
5957           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5958           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5959             cells.push_back(i);
5960         }
5961     }
5962 }
5963
5964 /*!
5965  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5966  * considered to be oriented correctly if an angle between its normal vector and a
5967  * given vector is less than \c PI / \c 2. 
5968  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5969  *         cells. 
5970  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5971  *         checked.
5972  *  \throw If \a this->getMeshDimension() != 2.
5973  *  \throw If \a this->getSpaceDimension() != 3.
5974  *
5975  *  \if ENABLE_EXAMPLES
5976  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5977  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5978  *  \endif
5979  *
5980  *  \sa changeOrientationOfCells
5981  */
5982 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5983 {
5984   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5985     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5986   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5987   const int *connI(_nodal_connec_index->getConstPointer());
5988   const double *coordsPtr(_coords->getConstPointer());
5989   bool isModified(false);
5990   for(int i=0;i<nbOfCells;i++)
5991     {
5992       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5993       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5994         {
5995           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5996           bool isQuadratic(cm.isQuadratic());
5997           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5998             {
5999               isModified=true;
6000               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6001             }
6002         }
6003     }
6004   if(isModified)
6005     _nodal_connec->declareAsNew();
6006   updateTime();
6007 }
6008
6009 /*!
6010  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6011  *
6012  * \sa orientCorrectly2DCells
6013  */
6014 void MEDCouplingUMesh::changeOrientationOfCells()
6015 {
6016   int mdim(getMeshDimension());
6017   if(mdim!=2 && mdim!=1)
6018     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6019   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6020   const int *connI(_nodal_connec_index->getConstPointer());
6021   if(mdim==2)
6022     {//2D
6023       for(int i=0;i<nbOfCells;i++)
6024         {
6025           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6026           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6027           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6028         }
6029     }
6030   else
6031     {//1D
6032       for(int i=0;i<nbOfCells;i++)
6033         {
6034           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6035           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6036           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6037         }
6038     }
6039 }
6040
6041 /*!
6042  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6043  * oriented facets. The normal vector of the facet should point out of the cell.
6044  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6045  *         is not cleared before filling in.
6046  *  \throw If \a this->getMeshDimension() != 3.
6047  *  \throw If \a this->getSpaceDimension() != 3.
6048  *  \throw If the coordinates array is not set.
6049  *  \throw If the nodal connectivity of cells is not defined.
6050  *
6051  *  \if ENABLE_EXAMPLES
6052  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6053  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6054  *  \endif
6055  */
6056 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6057 {
6058   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6059     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6060   int nbOfCells=getNumberOfCells();
6061   const int *conn=_nodal_connec->getConstPointer();
6062   const int *connI=_nodal_connec_index->getConstPointer();
6063   const double *coordsPtr=_coords->getConstPointer();
6064   for(int i=0;i<nbOfCells;i++)
6065     {
6066       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6067       if(type==INTERP_KERNEL::NORM_POLYHED)
6068         {
6069           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6070             cells.push_back(i);
6071         }
6072     }
6073 }
6074
6075 /*!
6076  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6077  * out of the cell. 
6078  *  \throw If \a this->getMeshDimension() != 3.
6079  *  \throw If \a this->getSpaceDimension() != 3.
6080  *  \throw If the coordinates array is not set.
6081  *  \throw If the nodal connectivity of cells is not defined.
6082  *  \throw If the reparation fails.
6083  *
6084  *  \if ENABLE_EXAMPLES
6085  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6086  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6087  *  \endif
6088  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6089  */
6090 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6091 {
6092   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6093     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6094   int nbOfCells=getNumberOfCells();
6095   int *conn=_nodal_connec->getPointer();
6096   const int *connI=_nodal_connec_index->getConstPointer();
6097   const double *coordsPtr=_coords->getConstPointer();
6098   for(int i=0;i<nbOfCells;i++)
6099     {
6100       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6101       if(type==INTERP_KERNEL::NORM_POLYHED)
6102         {
6103           try
6104           {
6105               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6106                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6107           }
6108           catch(INTERP_KERNEL::Exception& e)
6109           {
6110               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6111               throw INTERP_KERNEL::Exception(oss.str().c_str());
6112           }
6113         }
6114     }
6115   updateTime();
6116 }
6117
6118 /*!
6119  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6120  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6121  * according to which the first facet of the cell should be oriented to have the normal vector
6122  * pointing out of cell.
6123  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6124  *         cells. The caller is to delete this array using decrRef() as it is no more
6125  *         needed. 
6126  *  \throw If \a this->getMeshDimension() != 3.
6127  *  \throw If \a this->getSpaceDimension() != 3.
6128  *  \throw If the coordinates array is not set.
6129  *  \throw If the nodal connectivity of cells is not defined.
6130  *
6131  *  \if ENABLE_EXAMPLES
6132  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6133  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6134  *  \endif
6135  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6136  */
6137 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6138 {
6139   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6140   if(getMeshDimension()!=3)
6141     throw INTERP_KERNEL::Exception(msg);
6142   int spaceDim=getSpaceDimension();
6143   if(spaceDim!=3)
6144     throw INTERP_KERNEL::Exception(msg);
6145   //
6146   int nbOfCells=getNumberOfCells();
6147   int *conn=_nodal_connec->getPointer();
6148   const int *connI=_nodal_connec_index->getConstPointer();
6149   const double *coo=getCoords()->getConstPointer();
6150   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6151   for(int i=0;i<nbOfCells;i++)
6152     {
6153       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6154       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6155         {
6156           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6157             {
6158               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6159               cells->pushBackSilent(i);
6160             }
6161         }
6162     }
6163   return cells.retn();
6164 }
6165
6166 /*!
6167  * This method is a faster method to correct orientation of all 3D cells in \a this.
6168  * 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.
6169  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6170  * 
6171  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6172  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6173  */
6174 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6175 {
6176   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6177     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6178   int nbOfCells=getNumberOfCells();
6179   int *conn=_nodal_connec->getPointer();
6180   const int *connI=_nodal_connec_index->getConstPointer();
6181   const double *coordsPtr=_coords->getConstPointer();
6182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6183   for(int i=0;i<nbOfCells;i++)
6184     {
6185       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6186       switch(type)
6187       {
6188         case INTERP_KERNEL::NORM_TETRA4:
6189           {
6190             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6191               {
6192                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6193                 ret->pushBackSilent(i);
6194               }
6195             break;
6196           }
6197         case INTERP_KERNEL::NORM_PYRA5:
6198           {
6199             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6200               {
6201                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6202                 ret->pushBackSilent(i);
6203               }
6204             break;
6205           }
6206         case INTERP_KERNEL::NORM_PENTA6:
6207         case INTERP_KERNEL::NORM_HEXA8:
6208         case INTERP_KERNEL::NORM_HEXGP12:
6209           {
6210             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6211               {
6212                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6213                 ret->pushBackSilent(i);
6214               }
6215             break;
6216           }
6217         case INTERP_KERNEL::NORM_POLYHED:
6218           {
6219             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6220               {
6221                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6222                 ret->pushBackSilent(i);
6223               }
6224             break;
6225           }
6226         default:
6227           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 !");
6228       }
6229     }
6230   updateTime();
6231   return ret.retn();
6232 }
6233
6234 /*!
6235  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6236  * If it is not the case an exception will be thrown.
6237  * This method is fast because the first cell of \a this is used to compute the plane.
6238  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6239  * \param pos output of size at least 3 used to store a point owned of searched plane.
6240  */
6241 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6242 {
6243   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6244     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6245   const int *conn=_nodal_connec->getConstPointer();
6246   const int *connI=_nodal_connec_index->getConstPointer();
6247   const double *coordsPtr=_coords->getConstPointer();
6248   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6249   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6250 }
6251
6252 /*!
6253  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6254  * cells. Currently cells of the following types are treated:
6255  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6256  * For a cell of other type an exception is thrown.
6257  * Space dimension of a 2D mesh can be either 2 or 3.
6258  * The Edge Ratio of a cell \f$t\f$ is: 
6259  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6260  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6261  *  the smallest edge lengths of \f$t\f$.
6262  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6263  *          cells and one time, lying on \a this mesh. The caller is to delete this
6264  *          field using decrRef() as it is no more needed. 
6265  *  \throw If the coordinates array is not set.
6266  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6267  *  \throw If the connectivity data array has more than one component.
6268  *  \throw If the connectivity data array has a named component.
6269  *  \throw If the connectivity index data array has more than one component.
6270  *  \throw If the connectivity index data array has a named component.
6271  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6272  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6273  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6274  */
6275 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6276 {
6277   checkCoherency();
6278   int spaceDim=getSpaceDimension();
6279   int meshDim=getMeshDimension();
6280   if(spaceDim!=2 && spaceDim!=3)
6281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6282   if(meshDim!=2 && meshDim!=3)
6283     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6284   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6285   ret->setMesh(this);
6286   int nbOfCells=getNumberOfCells();
6287   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6288   arr->alloc(nbOfCells,1);
6289   double *pt=arr->getPointer();
6290   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6291   const int *conn=_nodal_connec->getConstPointer();
6292   const int *connI=_nodal_connec_index->getConstPointer();
6293   const double *coo=_coords->getConstPointer();
6294   double tmp[12];
6295   for(int i=0;i<nbOfCells;i++,pt++)
6296     {
6297       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6298       switch(t)
6299       {
6300         case INTERP_KERNEL::NORM_TRI3:
6301           {
6302             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6303             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6304             break;
6305           }
6306         case INTERP_KERNEL::NORM_QUAD4:
6307           {
6308             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6309             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6310             break;
6311           }
6312         case INTERP_KERNEL::NORM_TETRA4:
6313           {
6314             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6315             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6316             break;
6317           }
6318         default:
6319           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6320       }
6321       conn+=connI[i+1]-connI[i];
6322     }
6323   ret->setName("EdgeRatio");
6324   ret->synchronizeTimeWithSupport();
6325   return ret.retn();
6326 }
6327
6328 /*!
6329  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6330  * cells. Currently cells of the following types are treated:
6331  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6332  * For a cell of other type an exception is thrown.
6333  * Space dimension of a 2D mesh can be either 2 or 3.
6334  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6335  *          cells and one time, lying on \a this mesh. The caller is to delete this
6336  *          field using decrRef() as it is no more needed. 
6337  *  \throw If the coordinates array is not set.
6338  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6339  *  \throw If the connectivity data array has more than one component.
6340  *  \throw If the connectivity data array has a named component.
6341  *  \throw If the connectivity index data array has more than one component.
6342  *  \throw If the connectivity index data array has a named component.
6343  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6344  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6345  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6346  */
6347 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6348 {
6349   checkCoherency();
6350   int spaceDim=getSpaceDimension();
6351   int meshDim=getMeshDimension();
6352   if(spaceDim!=2 && spaceDim!=3)
6353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6354   if(meshDim!=2 && meshDim!=3)
6355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6357   ret->setMesh(this);
6358   int nbOfCells=getNumberOfCells();
6359   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6360   arr->alloc(nbOfCells,1);
6361   double *pt=arr->getPointer();
6362   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6363   const int *conn=_nodal_connec->getConstPointer();
6364   const int *connI=_nodal_connec_index->getConstPointer();
6365   const double *coo=_coords->getConstPointer();
6366   double tmp[12];
6367   for(int i=0;i<nbOfCells;i++,pt++)
6368     {
6369       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6370       switch(t)
6371       {
6372         case INTERP_KERNEL::NORM_TRI3:
6373           {
6374             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6375             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6376             break;
6377           }
6378         case INTERP_KERNEL::NORM_QUAD4:
6379           {
6380             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6381             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6382             break;
6383           }
6384         case INTERP_KERNEL::NORM_TETRA4:
6385           {
6386             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6387             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6388             break;
6389           }
6390         default:
6391           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6392       }
6393       conn+=connI[i+1]-connI[i];
6394     }
6395   ret->setName("AspectRatio");
6396   ret->synchronizeTimeWithSupport();
6397   return ret.retn();
6398 }
6399
6400 /*!
6401  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6402  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6403  * treated: INTERP_KERNEL::NORM_QUAD4.
6404  * For a cell of other type an exception is thrown.
6405  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6406  *          cells and one time, lying on \a this mesh. The caller is to delete this
6407  *          field using decrRef() as it is no more needed. 
6408  *  \throw If the coordinates array is not set.
6409  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6410  *  \throw If the connectivity data array has more than one component.
6411  *  \throw If the connectivity data array has a named component.
6412  *  \throw If the connectivity index data array has more than one component.
6413  *  \throw If the connectivity index data array has a named component.
6414  *  \throw If \a this->getMeshDimension() != 2.
6415  *  \throw If \a this->getSpaceDimension() != 3.
6416  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6417  */
6418 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6419 {
6420   checkCoherency();
6421   int spaceDim=getSpaceDimension();
6422   int meshDim=getMeshDimension();
6423   if(spaceDim!=3)
6424     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6425   if(meshDim!=2)
6426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6427   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6428   ret->setMesh(this);
6429   int nbOfCells=getNumberOfCells();
6430   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6431   arr->alloc(nbOfCells,1);
6432   double *pt=arr->getPointer();
6433   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6434   const int *conn=_nodal_connec->getConstPointer();
6435   const int *connI=_nodal_connec_index->getConstPointer();
6436   const double *coo=_coords->getConstPointer();
6437   double tmp[12];
6438   for(int i=0;i<nbOfCells;i++,pt++)
6439     {
6440       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6441       switch(t)
6442       {
6443         case INTERP_KERNEL::NORM_QUAD4:
6444           {
6445             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6446             *pt=INTERP_KERNEL::quadWarp(tmp);
6447             break;
6448           }
6449         default:
6450           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6451       }
6452       conn+=connI[i+1]-connI[i];
6453     }
6454   ret->setName("Warp");
6455   ret->synchronizeTimeWithSupport();
6456   return ret.retn();
6457 }
6458
6459
6460 /*!
6461  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6462  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6463  * treated: INTERP_KERNEL::NORM_QUAD4.
6464  * For a cell of other type an exception is thrown.
6465  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6466  *          cells and one time, lying on \a this mesh. The caller is to delete this
6467  *          field using decrRef() as it is no more needed. 
6468  *  \throw If the coordinates array is not set.
6469  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6470  *  \throw If the connectivity data array has more than one component.
6471  *  \throw If the connectivity data array has a named component.
6472  *  \throw If the connectivity index data array has more than one component.
6473  *  \throw If the connectivity index data array has a named component.
6474  *  \throw If \a this->getMeshDimension() != 2.
6475  *  \throw If \a this->getSpaceDimension() != 3.
6476  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6477  */
6478 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6479 {
6480   checkCoherency();
6481   int spaceDim=getSpaceDimension();
6482   int meshDim=getMeshDimension();
6483   if(spaceDim!=3)
6484     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6485   if(meshDim!=2)
6486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6487   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6488   ret->setMesh(this);
6489   int nbOfCells=getNumberOfCells();
6490   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6491   arr->alloc(nbOfCells,1);
6492   double *pt=arr->getPointer();
6493   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6494   const int *conn=_nodal_connec->getConstPointer();
6495   const int *connI=_nodal_connec_index->getConstPointer();
6496   const double *coo=_coords->getConstPointer();
6497   double tmp[12];
6498   for(int i=0;i<nbOfCells;i++,pt++)
6499     {
6500       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6501       switch(t)
6502       {
6503         case INTERP_KERNEL::NORM_QUAD4:
6504           {
6505             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6506             *pt=INTERP_KERNEL::quadSkew(tmp);
6507             break;
6508           }
6509         default:
6510           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6511       }
6512       conn+=connI[i+1]-connI[i];
6513     }
6514   ret->setName("Skew");
6515   ret->synchronizeTimeWithSupport();
6516   return ret.retn();
6517 }
6518
6519 /*!
6520  * 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.
6521  *
6522  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6523  *
6524  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6525  */
6526 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6527 {
6528   checkCoherency();
6529   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6530   ret->setMesh(this);
6531   std::set<INTERP_KERNEL::NormalizedCellType> types;
6532   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6533   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6534   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6535   arr->alloc(nbCells,1);
6536   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6537     {
6538       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6539       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6540       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6541     }
6542   ret->setArray(arr);
6543   ret->setName("Diameter");
6544   return ret.retn();
6545 }
6546
6547 /*!
6548  * This method aggregate the bbox of each cell and put it into bbox parameter.
6549  * 
6550  * \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)
6551  *                         For all other cases this input parameter is ignored.
6552  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6553  * 
6554  * \throw If \a this is not fully set (coordinates and connectivity).
6555  * \throw If a cell in \a this has no valid nodeId.
6556  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6557  */
6558 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6559 {
6560   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6561   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.
6562     return getBoundingBoxForBBTreeFast();
6563   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6564     {
6565       bool presenceOfQuadratic(false);
6566       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6567         {
6568           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6569           if(cm.isQuadratic())
6570             presenceOfQuadratic=true;
6571         }
6572       if(!presenceOfQuadratic)
6573         return getBoundingBoxForBBTreeFast();
6574       if(mDim==2 && sDim==2)
6575         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6576       else
6577         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6578     }
6579   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) !");
6580 }
6581
6582 /*!
6583  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6584  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6585  * 
6586  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6587  * 
6588  * \throw If \a this is not fully set (coordinates and connectivity).
6589  * \throw If a cell in \a this has no valid nodeId.
6590  */
6591 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6592 {
6593   checkFullyDefined();
6594   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6595   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6596   double *bbox(ret->getPointer());
6597   for(int i=0;i<nbOfCells*spaceDim;i++)
6598     {
6599       bbox[2*i]=std::numeric_limits<double>::max();
6600       bbox[2*i+1]=-std::numeric_limits<double>::max();
6601     }
6602   const double *coordsPtr(_coords->getConstPointer());
6603   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6604   for(int i=0;i<nbOfCells;i++)
6605     {
6606       int offset=connI[i]+1;
6607       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6608       for(int j=0;j<nbOfNodesForCell;j++)
6609         {
6610           int nodeId=conn[offset+j];
6611           if(nodeId>=0 && nodeId<nbOfNodes)
6612             {
6613               for(int k=0;k<spaceDim;k++)
6614                 {
6615                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6616                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6617                 }
6618               kk++;
6619             }
6620         }
6621       if(kk==0)
6622         {
6623           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6624           throw INTERP_KERNEL::Exception(oss.str().c_str());
6625         }
6626     }
6627   return ret.retn();
6628 }
6629
6630 /*!
6631  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6632  * useful for 2D meshes having quadratic cells
6633  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6634  * the two extremities of the arc of circle).
6635  * 
6636  * \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)
6637  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6638  * \throw If \a this is not fully defined.
6639  * \throw If \a this is not a mesh with meshDimension equal to 2.
6640  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6641  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6642  */
6643 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6644 {
6645   checkFullyDefined();
6646   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6647   if(spaceDim!=2 || mDim!=2)
6648     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!");
6649   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6650   double *bbox(ret->getPointer());
6651   const double *coords(_coords->getConstPointer());
6652   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6653   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6654     {
6655       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6656       int sz(connI[1]-connI[0]-1);
6657       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6658       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6659       INTERP_KERNEL::QuadraticPolygon *pol(0);
6660       for(int j=0;j<sz;j++)
6661         {
6662           int nodeId(conn[*connI+1+j]);
6663           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6664         }
6665       if(!cm.isQuadratic())
6666         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6667       else
6668         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6669       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6670       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6671     }
6672   return ret.retn();
6673 }
6674
6675 /*!
6676  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6677  * useful for 2D meshes having quadratic cells
6678  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6679  * the two extremities of the arc of circle).
6680  * 
6681  * \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)
6682  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6683  * \throw If \a this is not fully defined.
6684  * \throw If \a this is not a mesh with meshDimension equal to 1.
6685  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6686  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6687  */
6688 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6689 {
6690   checkFullyDefined();
6691   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6692   if(spaceDim!=2 || mDim!=1)
6693     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!");
6694   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6695   double *bbox(ret->getPointer());
6696   const double *coords(_coords->getConstPointer());
6697   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6698   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6699     {
6700       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6701       int sz(connI[1]-connI[0]-1);
6702       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6703       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6704       INTERP_KERNEL::Edge *edge(0);
6705       for(int j=0;j<sz;j++)
6706         {
6707           int nodeId(conn[*connI+1+j]);
6708           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6709         }
6710       if(!cm.isQuadratic())
6711         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6712       else
6713         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6714       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6715       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6716     }
6717   return ret.retn();
6718 }
6719
6720 /// @cond INTERNAL
6721
6722 namespace ParaMEDMEMImpl
6723 {
6724   class ConnReader
6725   {
6726   public:
6727     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6728     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6729   private:
6730     const int *_conn;
6731     int _val;
6732   };
6733
6734   class ConnReader2
6735   {
6736   public:
6737     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6738     bool operator() (const int& pos) { return _conn[pos]==_val; }
6739   private:
6740     const int *_conn;
6741     int _val;
6742   };
6743 }
6744
6745 /// @endcond
6746
6747 /*!
6748  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6749  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6750  * \a this is composed in cell types.
6751  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6752  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6753  * This parameter is kept only for compatibility with other methode listed above.
6754  */
6755 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6756 {
6757   checkConnectivityFullyDefined();
6758   const int *conn=_nodal_connec->getConstPointer();
6759   const int *connI=_nodal_connec_index->getConstPointer();
6760   const int *work=connI;
6761   int nbOfCells=getNumberOfCells();
6762   std::size_t n=getAllGeoTypes().size();
6763   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6764   std::set<INTERP_KERNEL::NormalizedCellType> types;
6765   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6766     {
6767       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6768       if(types.find(typ)!=types.end())
6769         {
6770           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6771           oss << " is not contiguous !";
6772           throw INTERP_KERNEL::Exception(oss.str().c_str());
6773         }
6774       types.insert(typ);
6775       ret[3*i]=typ;
6776       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6777       ret[3*i+1]=(int)std::distance(work,work2);
6778       work=work2;
6779     }
6780   return ret;
6781 }
6782
6783 /*!
6784  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6785  * only for types cell, type node is not managed.
6786  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6787  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6788  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6789  * If 2 or more same geometric type is in \a code and exception is thrown too.
6790  *
6791  * This method firstly checks
6792  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6793  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6794  * an exception is thrown too.
6795  * 
6796  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6797  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6798  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6799  */
6800 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6801 {
6802   if(code.empty())
6803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6804   std::size_t sz=code.size();
6805   std::size_t n=sz/3;
6806   if(sz%3!=0)
6807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6808   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6809   int nb=0;
6810   bool isNoPflUsed=true;
6811   for(std::size_t i=0;i<n;i++)
6812     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6813       {
6814         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6815         nb+=code[3*i+1];
6816         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6817           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6818         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6819       }
6820   if(types.size()!=n)
6821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6822   if(isNoPflUsed)
6823     {
6824       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6825         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6826       if(types.size()==_types.size())
6827         return 0;
6828     }
6829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6830   ret->alloc(nb,1);
6831   int *retPtr=ret->getPointer();
6832   const int *connI=_nodal_connec_index->getConstPointer();
6833   const int *conn=_nodal_connec->getConstPointer();
6834   int nbOfCells=getNumberOfCells();
6835   const int *i=connI;
6836   int kk=0;
6837   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6838     {
6839       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6840       int offset=(int)std::distance(connI,i);
6841       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6842       int nbOfCellsOfCurType=(int)std::distance(i,j);
6843       if(code[3*kk+2]==-1)
6844         for(int k=0;k<nbOfCellsOfCurType;k++)
6845           *retPtr++=k+offset;
6846       else
6847         {
6848           int idInIdsPerType=code[3*kk+2];
6849           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6850             {
6851               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6852               if(zePfl)
6853                 {
6854                   zePfl->checkAllocated();
6855                   if(zePfl->getNumberOfComponents()==1)
6856                     {
6857                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6858                         {
6859                           if(*k>=0 && *k<nbOfCellsOfCurType)
6860                             *retPtr=(*k)+offset;
6861                           else
6862                             {
6863                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6864                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6865                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6866                             }
6867                         }
6868                     }
6869                   else
6870                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6871                 }
6872               else
6873                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6874             }
6875           else
6876             {
6877               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6878               oss << " should be in [0," << idsPerType.size() << ") !";
6879               throw INTERP_KERNEL::Exception(oss.str().c_str());
6880             }
6881         }
6882       i=j;
6883     }
6884   return ret.retn();
6885 }
6886
6887 /*!
6888  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6889  * 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.
6890  * 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.
6891  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6892  * 
6893  * \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.
6894  * \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,
6895  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6896  * \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.
6897  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6898  * \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
6899  */
6900 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6901 {
6902   if(!profile)
6903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6904   if(profile->getNumberOfComponents()!=1)
6905     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6906   checkConnectivityFullyDefined();
6907   const int *conn=_nodal_connec->getConstPointer();
6908   const int *connI=_nodal_connec_index->getConstPointer();
6909   int nbOfCells=getNumberOfCells();
6910   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6911   std::vector<int> typeRangeVals(1);
6912   for(const int *i=connI;i!=connI+nbOfCells;)
6913     {
6914       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6915       if(std::find(types.begin(),types.end(),curType)!=types.end())
6916         {
6917           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6918         }
6919       types.push_back(curType);
6920       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6921       typeRangeVals.push_back((int)std::distance(connI,i));
6922     }
6923   //
6924   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6925   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6929   //
6930   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6931   code.resize(3*nbOfCastsFinal);
6932   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6933   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6934   for(int i=0;i<nbOfCastsFinal;i++)
6935     {
6936       int castId=castsPresent->getIJ(i,0);
6937       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6938       idsInPflPerType2.push_back(tmp3);
6939       code[3*i]=(int)types[castId];
6940       code[3*i+1]=tmp3->getNumberOfTuples();
6941       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6942       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6943         {
6944           tmp4->copyStringInfoFrom(*profile);
6945           idsPerType2.push_back(tmp4);
6946           code[3*i+2]=(int)idsPerType2.size()-1;
6947         }
6948       else
6949         {
6950           code[3*i+2]=-1;
6951         }
6952     }
6953   std::size_t sz2=idsInPflPerType2.size();
6954   idsInPflPerType.resize(sz2);
6955   for(std::size_t i=0;i<sz2;i++)
6956     {
6957       DataArrayInt *locDa=idsInPflPerType2[i];
6958       locDa->incrRef();
6959       idsInPflPerType[i]=locDa;
6960     }
6961   std::size_t sz=idsPerType2.size();
6962   idsPerType.resize(sz);
6963   for(std::size_t i=0;i<sz;i++)
6964     {
6965       DataArrayInt *locDa=idsPerType2[i];
6966       locDa->incrRef();
6967       idsPerType[i]=locDa;
6968     }
6969 }
6970
6971 /*!
6972  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6973  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6974  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6975  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
6976  */
6977 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6978 {
6979   checkFullyDefined();
6980   nM1LevMesh->checkFullyDefined();
6981   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6982     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6983   if(_coords!=nM1LevMesh->getCoords())
6984     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6985   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6986   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6987   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6989   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6990   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6991   tmp->setConnectivity(tmp0,tmp1);
6992   tmp->renumberCells(ret0->getConstPointer(),false);
6993   revDesc=tmp->getNodalConnectivity();
6994   revDescIndx=tmp->getNodalConnectivityIndex();
6995   DataArrayInt *ret=0;
6996   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6997     {
6998       int tmp2;
6999       ret->getMaxValue(tmp2);
7000       ret->decrRef();
7001       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7002       throw INTERP_KERNEL::Exception(oss.str().c_str());
7003     }
7004   nM1LevMeshIds=ret;
7005   //
7006   revDesc->incrRef();
7007   revDescIndx->incrRef();
7008   ret1->incrRef();
7009   ret0->incrRef();
7010   meshnM1Old2New=ret0;
7011   return ret1;
7012 }
7013
7014 /*!
7015  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7016  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7017  * in "Old to New" mode.
7018  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7019  *          this array using decrRef() as it is no more needed.
7020  *  \throw If the nodal connectivity of cells is not defined.
7021  */
7022 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7023 {
7024   checkConnectivityFullyDefined();
7025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7026   renumberCells(ret->getConstPointer(),false);
7027   return ret.retn();
7028 }
7029
7030 /*!
7031  * This methods checks that cells are sorted by their types.
7032  * This method makes asumption (no check) that connectivity is correctly set before calling.
7033  */
7034 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7035 {
7036   checkFullyDefined();
7037   const int *conn=_nodal_connec->getConstPointer();
7038   const int *connI=_nodal_connec_index->getConstPointer();
7039   int nbOfCells=getNumberOfCells();
7040   std::set<INTERP_KERNEL::NormalizedCellType> types;
7041   for(const int *i=connI;i!=connI+nbOfCells;)
7042     {
7043       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7044       if(types.find(curType)!=types.end())
7045         return false;
7046       types.insert(curType);
7047       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7048     }
7049   return true;
7050 }
7051
7052 /*!
7053  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7054  * The geometric type order is specified by MED file.
7055  * 
7056  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7057  */
7058 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7059 {
7060   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7061 }
7062
7063 /*!
7064  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7065  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7066  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7067  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7068  */
7069 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7070 {
7071   checkFullyDefined();
7072   const int *conn=_nodal_connec->getConstPointer();
7073   const int *connI=_nodal_connec_index->getConstPointer();
7074   int nbOfCells=getNumberOfCells();
7075   if(nbOfCells==0)
7076     return true;
7077   int lastPos=-1;
7078   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7079   for(const int *i=connI;i!=connI+nbOfCells;)
7080     {
7081       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7082       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7083       if(isTypeExists!=orderEnd)
7084         {
7085           int pos=(int)std::distance(orderBg,isTypeExists);
7086           if(pos<=lastPos)
7087             return false;
7088           lastPos=pos;
7089           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7090         }
7091       else
7092         {
7093           if(sg.find(curType)==sg.end())
7094             {
7095               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7096               sg.insert(curType);
7097             }
7098           else
7099             return false;
7100         }
7101     }
7102   return true;
7103 }
7104
7105 /*!
7106  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7107  * 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
7108  * 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'.
7109  */
7110 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7111 {
7112   checkConnectivityFullyDefined();
7113   int nbOfCells=getNumberOfCells();
7114   const int *conn=_nodal_connec->getConstPointer();
7115   const int *connI=_nodal_connec_index->getConstPointer();
7116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7118   tmpa->alloc(nbOfCells,1);
7119   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7120   tmpb->fillWithZero();
7121   int *tmp=tmpa->getPointer();
7122   int *tmp2=tmpb->getPointer();
7123   for(const int *i=connI;i!=connI+nbOfCells;i++)
7124     {
7125       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7126       if(where!=orderEnd)
7127         {
7128           int pos=(int)std::distance(orderBg,where);
7129           tmp2[pos]++;
7130           tmp[std::distance(connI,i)]=pos;
7131         }
7132       else
7133         {
7134           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7135           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7136           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7137           throw INTERP_KERNEL::Exception(oss.str().c_str());
7138         }
7139     }
7140   nbPerType=tmpb.retn();
7141   return tmpa.retn();
7142 }
7143
7144 /*!
7145  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7146  *
7147  * \return a new object containing the old to new correspondance.
7148  *
7149  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7150  */
7151 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7152 {
7153   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7154 }
7155
7156 /*!
7157  * 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.
7158  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7159  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7160  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7161  */
7162 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7163 {
7164   DataArrayInt *nbPerType=0;
7165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7166   nbPerType->decrRef();
7167   return tmpa->buildPermArrPerLevel();
7168 }
7169
7170 /*!
7171  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7172  * The number of cells remains unchanged after the call of this method.
7173  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7174  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7175  *
7176  * \return the array giving the correspondance old to new.
7177  */
7178 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7179 {
7180   checkFullyDefined();
7181   computeTypes();
7182   const int *conn=_nodal_connec->getConstPointer();
7183   const int *connI=_nodal_connec_index->getConstPointer();
7184   int nbOfCells=getNumberOfCells();
7185   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7186   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7187     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7188       {
7189         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7190         types.push_back(curType);
7191         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7192       }
7193   DataArrayInt *ret=DataArrayInt::New();
7194   ret->alloc(nbOfCells,1);
7195   int *retPtr=ret->getPointer();
7196   std::fill(retPtr,retPtr+nbOfCells,-1);
7197   int newCellId=0;
7198   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7199     {
7200       for(const int *i=connI;i!=connI+nbOfCells;i++)
7201         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7202           retPtr[std::distance(connI,i)]=newCellId++;
7203     }
7204   renumberCells(retPtr,false);
7205   return ret;
7206 }
7207
7208 /*!
7209  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7210  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7211  * This method makes asumption that connectivity is correctly set before calling.
7212  */
7213 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7214 {
7215   checkConnectivityFullyDefined();
7216   const int *conn=_nodal_connec->getConstPointer();
7217   const int *connI=_nodal_connec_index->getConstPointer();
7218   int nbOfCells=getNumberOfCells();
7219   std::vector<MEDCouplingUMesh *> ret;
7220   for(const int *i=connI;i!=connI+nbOfCells;)
7221     {
7222       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7223       int beginCellId=(int)std::distance(connI,i);
7224       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7225       int endCellId=(int)std::distance(connI,i);
7226       int sz=endCellId-beginCellId;
7227       int *cells=new int[sz];
7228       for(int j=0;j<sz;j++)
7229         cells[j]=beginCellId+j;
7230       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7231       delete [] cells;
7232       ret.push_back(m);
7233     }
7234   return ret;
7235 }
7236
7237 /*!
7238  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7239  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7240  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7241  *
7242  * \return a newly allocated instance, that the caller must manage.
7243  * \throw If \a this contains more than one geometric type.
7244  * \throw If the nodal connectivity of \a this is not fully defined.
7245  * \throw If the internal data is not coherent.
7246  */
7247 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7248 {
7249   checkConnectivityFullyDefined();
7250   if(_types.size()!=1)
7251     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7252   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7253   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7254   ret->setCoords(getCoords());
7255   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7256   if(retC)
7257     {
7258       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7259       retC->setNodalConnectivity(c);
7260     }
7261   else
7262     {
7263       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7264       if(!retD)
7265         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7266       DataArrayInt *c=0,*ci=0;
7267       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7268       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7269       retD->setNodalConnectivity(cs,cis);
7270     }
7271   return ret.retn();
7272 }
7273
7274 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7275 {
7276   checkConnectivityFullyDefined();
7277   if(_types.size()!=1)
7278     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7279   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7280   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7281   if(cm.isDynamic())
7282     {
7283       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7284       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7285       throw INTERP_KERNEL::Exception(oss.str().c_str());
7286     }
7287   int nbCells=getNumberOfCells();
7288   int typi=(int)typ;
7289   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7291   int *outPtr=connOut->getPointer();
7292   const int *conn=_nodal_connec->begin();
7293   const int *connI=_nodal_connec_index->begin();
7294   nbNodesPerCell++;
7295   for(int i=0;i<nbCells;i++,connI++)
7296     {
7297       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7298         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7299       else
7300         {
7301           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 << ") !";
7302           throw INTERP_KERNEL::Exception(oss.str().c_str());
7303         }
7304     }
7305   return connOut.retn();
7306 }
7307
7308 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7309 {
7310   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7311   checkConnectivityFullyDefined();
7312   if(_types.size()!=1)
7313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7314   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7315   if(lgth<nbCells)
7316     throw INTERP_KERNEL::Exception(msg0);
7317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7318   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7319   int *cp(c->getPointer()),*cip(ci->getPointer());
7320   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7321   cip[0]=0;
7322   for(int i=0;i<nbCells;i++,cip++,incip++)
7323     {
7324       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7325       int delta(stop-strt);
7326       if(delta>=1)
7327         {
7328           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7329             cp=std::copy(incp+strt,incp+stop,cp);
7330           else
7331             throw INTERP_KERNEL::Exception(msg0);
7332         }
7333       else
7334         throw INTERP_KERNEL::Exception(msg0);
7335       cip[1]=cip[0]+delta;
7336     }
7337   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7338 }
7339
7340 /*!
7341  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7342  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7343  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7344  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7345  * are not used here to avoid the build of big permutation array.
7346  *
7347  * \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
7348  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7349  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7350  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7351  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7352  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7353  * \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
7354  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7355  */
7356 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7357                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7358                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7359 {
7360   std::vector<const MEDCouplingUMesh *> ms2;
7361   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7362     if(*it)
7363       {
7364         (*it)->checkConnectivityFullyDefined();
7365         ms2.push_back(*it);
7366       }
7367   if(ms2.empty())
7368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7369   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7370   int meshDim=ms2[0]->getMeshDimension();
7371   std::vector<const MEDCouplingUMesh *> m1ssm;
7372   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7373   //
7374   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7375   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7376   int fake=0,rk=0;
7377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7378   ret1->alloc(0,1); ret2->alloc(0,1);
7379   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7380     {
7381       if(meshDim!=(*it)->getMeshDimension())
7382         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7383       if(refCoo!=(*it)->getCoords())
7384         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7385       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7386       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7387       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7388       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7389         {
7390           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7391           m1ssmSingleAuto.push_back(singleCell);
7392           m1ssmSingle.push_back(singleCell);
7393           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7394         }
7395     }
7396   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7398   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7399   for(std::size_t i=0;i<m1ssm.size();i++)
7400     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7402   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7403   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7404   return ret0.retn();
7405 }
7406
7407 /*!
7408  * This method returns a newly created DataArrayInt instance.
7409  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7410  */
7411 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7412 {
7413   checkFullyDefined();
7414   const int *conn=_nodal_connec->getConstPointer();
7415   const int *connIndex=_nodal_connec_index->getConstPointer();
7416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7417   for(const int *w=begin;w!=end;w++)
7418     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7419       ret->pushBackSilent(*w);
7420   return ret.retn();
7421 }
7422
7423 /*!
7424  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7425  * are in [0:getNumberOfCells())
7426  */
7427 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7428 {
7429   checkFullyDefined();
7430   const int *conn=_nodal_connec->getConstPointer();
7431   const int *connI=_nodal_connec_index->getConstPointer();
7432   int nbOfCells=getNumberOfCells();
7433   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7434   int *tmp=new int[nbOfCells];
7435   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7436     {
7437       int j=0;
7438       for(const int *i=connI;i!=connI+nbOfCells;i++)
7439         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7440           tmp[std::distance(connI,i)]=j++;
7441     }
7442   DataArrayInt *ret=DataArrayInt::New();
7443   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7444   ret->copyStringInfoFrom(*da);
7445   int *retPtr=ret->getPointer();
7446   const int *daPtr=da->getConstPointer();
7447   int nbOfElems=da->getNbOfElems();
7448   for(int k=0;k<nbOfElems;k++)
7449     retPtr[k]=tmp[daPtr[k]];
7450   delete [] tmp;
7451   return ret;
7452 }
7453
7454 /*!
7455  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7456  * This method \b works \b for mesh sorted by type.
7457  * cells whose ids is in 'idsPerGeoType' array.
7458  * This method conserves coords and name of mesh.
7459  */
7460 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7461 {
7462   std::vector<int> code=getDistributionOfTypes();
7463   std::size_t nOfTypesInThis=code.size()/3;
7464   int sz=0,szOfType=0;
7465   for(std::size_t i=0;i<nOfTypesInThis;i++)
7466     {
7467       if(code[3*i]!=type)
7468         sz+=code[3*i+1];
7469       else
7470         szOfType=code[3*i+1];
7471     }
7472   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7473     if(*work<0 || *work>=szOfType)
7474       {
7475         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7476         oss << ". It should be in [0," << szOfType << ") !";
7477         throw INTERP_KERNEL::Exception(oss.str().c_str());
7478       }
7479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7480   int *idsPtr=idsTokeep->getPointer();
7481   int offset=0;
7482   for(std::size_t i=0;i<nOfTypesInThis;i++)
7483     {
7484       if(code[3*i]!=type)
7485         for(int j=0;j<code[3*i+1];j++)
7486           *idsPtr++=offset+j;
7487       else
7488         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7489       offset+=code[3*i+1];
7490     }
7491   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7492   ret->copyTinyInfoFrom(this);
7493   return ret.retn();
7494 }
7495
7496 /*!
7497  * This method returns a vector of size 'this->getNumberOfCells()'.
7498  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7499  */
7500 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7501 {
7502   int ncell=getNumberOfCells();
7503   std::vector<bool> ret(ncell);
7504   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7505   const int *c=getNodalConnectivity()->getConstPointer();
7506   for(int i=0;i<ncell;i++)
7507     {
7508       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7509       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7510       ret[i]=cm.isQuadratic();
7511     }
7512   return ret;
7513 }
7514
7515 /*!
7516  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7517  */
7518 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7519 {
7520   if(other->getType()!=UNSTRUCTURED)
7521     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7522   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7523   return MergeUMeshes(this,otherC);
7524 }
7525
7526 /*!
7527  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7528  * computed by averaging coordinates of cell nodes, so this method is not a right
7529  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7530  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7531  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7532  *          components. The caller is to delete this array using decrRef() as it is
7533  *          no more needed.
7534  *  \throw If the coordinates array is not set.
7535  *  \throw If the nodal connectivity of cells is not defined.
7536  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7537  */
7538 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7539 {
7540   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7541   int spaceDim=getSpaceDimension();
7542   int nbOfCells=getNumberOfCells();
7543   ret->alloc(nbOfCells,spaceDim);
7544   ret->copyStringInfoFrom(*getCoords());
7545   double *ptToFill=ret->getPointer();
7546   const int *nodal=_nodal_connec->getConstPointer();
7547   const int *nodalI=_nodal_connec_index->getConstPointer();
7548   const double *coor=_coords->getConstPointer();
7549   for(int i=0;i<nbOfCells;i++)
7550     {
7551       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7552       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7553       ptToFill+=spaceDim;
7554     }
7555   return ret.retn();
7556 }
7557
7558 /*!
7559  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7560  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7561  * 
7562  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7563  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7564  * 
7565  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7566  * \throw If \a this is not fully defined (coordinates and connectivity)
7567  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7568  */
7569 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7570 {
7571   checkFullyDefined();
7572   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7573   int spaceDim=getSpaceDimension();
7574   int nbOfCells=getNumberOfCells();
7575   int nbOfNodes=getNumberOfNodes();
7576   ret->alloc(nbOfCells,spaceDim);
7577   double *ptToFill=ret->getPointer();
7578   const int *nodal=_nodal_connec->getConstPointer();
7579   const int *nodalI=_nodal_connec_index->getConstPointer();
7580   const double *coor=_coords->getConstPointer();
7581   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7582     {
7583       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7584       std::fill(ptToFill,ptToFill+spaceDim,0.);
7585       if(type!=INTERP_KERNEL::NORM_POLYHED)
7586         {
7587           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7588             {
7589               if(*conn>=0 && *conn<nbOfNodes)
7590                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7591               else
7592                 {
7593                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7594                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7595                 }
7596             }
7597           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7598           if(nbOfNodesInCell>0)
7599             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7600           else
7601             {
7602               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7603               throw INTERP_KERNEL::Exception(oss.str().c_str());
7604             }
7605         }
7606       else
7607         {
7608           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7609           s.erase(-1);
7610           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7611             {
7612               if(*it>=0 && *it<nbOfNodes)
7613                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7614               else
7615                 {
7616                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7617                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7618                 }
7619             }
7620           if(!s.empty())
7621             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7622           else
7623             {
7624               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7625               throw INTERP_KERNEL::Exception(oss.str().c_str());
7626             }
7627         }
7628     }
7629   return ret.retn();
7630 }
7631
7632 /*!
7633  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7634  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7635  * are specified via an array of cell ids. 
7636  *  \warning Validity of the specified cell ids is not checked! 
7637  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7638  *  \param [in] begin - an array of cell ids of interest.
7639  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7640  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7641  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7642  *          caller is to delete this array using decrRef() as it is no more needed. 
7643  *  \throw If the coordinates array is not set.
7644  *  \throw If the nodal connectivity of cells is not defined.
7645  *
7646  *  \if ENABLE_EXAMPLES
7647  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7648  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7649  *  \endif
7650  */
7651 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7652 {
7653   DataArrayDouble *ret=DataArrayDouble::New();
7654   int spaceDim=getSpaceDimension();
7655   int nbOfTuple=(int)std::distance(begin,end);
7656   ret->alloc(nbOfTuple,spaceDim);
7657   double *ptToFill=ret->getPointer();
7658   double *tmp=new double[spaceDim];
7659   const int *nodal=_nodal_connec->getConstPointer();
7660   const int *nodalI=_nodal_connec_index->getConstPointer();
7661   const double *coor=_coords->getConstPointer();
7662   for(const int *w=begin;w!=end;w++)
7663     {
7664       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7665       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7666       ptToFill+=spaceDim;
7667     }
7668   delete [] tmp;
7669   return ret;
7670 }
7671
7672 /*!
7673  * 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".
7674  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7675  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7676  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7677  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7678  * 
7679  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7680  * \throw If spaceDim!=3 or meshDim!=2.
7681  * \throw If connectivity of \a this is invalid.
7682  * \throw If connectivity of a cell in \a this points to an invalid node.
7683  */
7684 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7685 {
7686   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7687   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7688   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7689     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7690   ret->alloc(nbOfCells,4);
7691   double *retPtr(ret->getPointer());
7692   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7693   const double *coor(_coords->begin());
7694   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7695     {
7696       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7697       if(nodalI[1]-nodalI[0]>=3)
7698         {
7699           for(int j=0;j<3;j++)
7700             {
7701               int nodeId(nodal[nodalI[0]+1+j]);
7702               if(nodeId>=0 && nodeId<nbOfNodes)
7703                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7704               else
7705                 {
7706                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7707                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7708                 }
7709             }
7710         }
7711       else
7712         {
7713           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7714           throw INTERP_KERNEL::Exception(oss.str().c_str());
7715         }
7716       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7717       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7718     }
7719   return ret.retn();
7720 }
7721
7722 /*!
7723  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7724  * 
7725  */
7726 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7727 {
7728   if(!da)
7729     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7730   da->checkAllocated();
7731   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7732   ret->setCoords(da);
7733   int nbOfTuples=da->getNumberOfTuples();
7734   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7735   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7736   c->alloc(2*nbOfTuples,1);
7737   cI->alloc(nbOfTuples+1,1);
7738   int *cp=c->getPointer();
7739   int *cip=cI->getPointer();
7740   *cip++=0;
7741   for(int i=0;i<nbOfTuples;i++)
7742     {
7743       *cp++=INTERP_KERNEL::NORM_POINT1;
7744       *cp++=i;
7745       *cip++=2*(i+1);
7746     }
7747   ret->setConnectivity(c,cI,true);
7748   return ret.retn();
7749 }
7750 /*!
7751  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7752  * Cells and nodes of
7753  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7754  *  \param [in] mesh1 - the first mesh.
7755  *  \param [in] mesh2 - the second mesh.
7756  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7757  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7758  *          is no more needed.
7759  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7760  *  \throw If the coordinates array is not set in none of the meshes.
7761  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7762  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7763  */
7764 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7765 {
7766   std::vector<const MEDCouplingUMesh *> tmp(2);
7767   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7768   return MergeUMeshes(tmp);
7769 }
7770
7771 /*!
7772  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7773  * Cells and nodes of
7774  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7775  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7776  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7777  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7778  *          is no more needed.
7779  *  \throw If \a a.size() == 0.
7780  *  \throw If \a a[ *i* ] == NULL.
7781  *  \throw If the coordinates array is not set in none of the meshes.
7782  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7783  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7784  */
7785 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7786 {
7787   std::size_t sz=a.size();
7788   if(sz==0)
7789     return MergeUMeshesLL(a);
7790   for(std::size_t ii=0;ii<sz;ii++)
7791     if(!a[ii])
7792       {
7793         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7794         throw INTERP_KERNEL::Exception(oss.str().c_str());
7795       }
7796   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7797   std::vector< const MEDCouplingUMesh * > aa(sz);
7798   int spaceDim=-3;
7799   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7800     {
7801       const MEDCouplingUMesh *cur=a[i];
7802       const DataArrayDouble *coo=cur->getCoords();
7803       if(coo)
7804         spaceDim=coo->getNumberOfComponents();
7805     }
7806   if(spaceDim==-3)
7807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7808   for(std::size_t i=0;i<sz;i++)
7809     {
7810       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7811       aa[i]=bb[i];
7812     }
7813   return MergeUMeshesLL(aa);
7814 }
7815
7816 /// @cond INTERNAL
7817
7818 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7819 {
7820   if(a.empty())
7821     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7822   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7823   int meshDim=(*it)->getMeshDimension();
7824   int nbOfCells=(*it)->getNumberOfCells();
7825   int meshLgth=(*it++)->getMeshLength();
7826   for(;it!=a.end();it++)
7827     {
7828       if(meshDim!=(*it)->getMeshDimension())
7829         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7830       nbOfCells+=(*it)->getNumberOfCells();
7831       meshLgth+=(*it)->getMeshLength();
7832     }
7833   std::vector<const MEDCouplingPointSet *> aps(a.size());
7834   std::copy(a.begin(),a.end(),aps.begin());
7835   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7836   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7837   ret->setCoords(pts);
7838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7839   c->alloc(meshLgth,1);
7840   int *cPtr=c->getPointer();
7841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7842   cI->alloc(nbOfCells+1,1);
7843   int *cIPtr=cI->getPointer();
7844   *cIPtr++=0;
7845   int offset=0;
7846   int offset2=0;
7847   for(it=a.begin();it!=a.end();it++)
7848     {
7849       int curNbOfCell=(*it)->getNumberOfCells();
7850       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7851       const int *curC=(*it)->_nodal_connec->getConstPointer();
7852       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7853       for(int j=0;j<curNbOfCell;j++)
7854         {
7855           const int *src=curC+curCI[j];
7856           *cPtr++=*src++;
7857           for(;src!=curC+curCI[j+1];src++,cPtr++)
7858             {
7859               if(*src!=-1)
7860                 *cPtr=*src+offset2;
7861               else
7862                 *cPtr=-1;
7863             }
7864         }
7865       offset+=curCI[curNbOfCell];
7866       offset2+=(*it)->getNumberOfNodes();
7867     }
7868   //
7869   ret->setConnectivity(c,cI,true);
7870   return ret.retn();
7871 }
7872
7873 /// @endcond
7874
7875 /*!
7876  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7877  * dimension and sharing the node coordinates array.
7878  * All cells of the first mesh precede all cells of the second mesh
7879  * within the result mesh. 
7880  *  \param [in] mesh1 - the first mesh.
7881  *  \param [in] mesh2 - the second mesh.
7882  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7883  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7884  *          is no more needed.
7885  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7886  *  \throw If the meshes do not share the node coordinates array.
7887  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7888  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7889  */
7890 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7891 {
7892   std::vector<const MEDCouplingUMesh *> tmp(2);
7893   tmp[0]=mesh1; tmp[1]=mesh2;
7894   return MergeUMeshesOnSameCoords(tmp);
7895 }
7896
7897 /*!
7898  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7899  * dimension and sharing the node coordinates array.
7900  * All cells of the *i*-th mesh precede all cells of the
7901  * (*i*+1)-th mesh within the result mesh.
7902  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7903  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7904  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7905  *          is no more needed.
7906  *  \throw If \a a.size() == 0.
7907  *  \throw If \a a[ *i* ] == NULL.
7908  *  \throw If the meshes do not share the node coordinates array.
7909  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7910  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7911  */
7912 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7913 {
7914   if(meshes.empty())
7915     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7916   for(std::size_t ii=0;ii<meshes.size();ii++)
7917     if(!meshes[ii])
7918       {
7919         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7920         throw INTERP_KERNEL::Exception(oss.str().c_str());
7921       }
7922   const DataArrayDouble *coords=meshes.front()->getCoords();
7923   int meshDim=meshes.front()->getMeshDimension();
7924   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7925   int meshLgth=0;
7926   int meshIndexLgth=0;
7927   for(;iter!=meshes.end();iter++)
7928     {
7929       if(coords!=(*iter)->getCoords())
7930         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7931       if(meshDim!=(*iter)->getMeshDimension())
7932         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7933       meshLgth+=(*iter)->getMeshLength();
7934       meshIndexLgth+=(*iter)->getNumberOfCells();
7935     }
7936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7937   nodal->alloc(meshLgth,1);
7938   int *nodalPtr=nodal->getPointer();
7939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7940   nodalIndex->alloc(meshIndexLgth+1,1);
7941   int *nodalIndexPtr=nodalIndex->getPointer();
7942   int offset=0;
7943   for(iter=meshes.begin();iter!=meshes.end();iter++)
7944     {
7945       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7946       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7947       int nbOfCells=(*iter)->getNumberOfCells();
7948       int meshLgth2=(*iter)->getMeshLength();
7949       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7950       if(iter!=meshes.begin())
7951         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7952       else
7953         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7954       offset+=meshLgth2;
7955     }
7956   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7957   ret->setName("merge");
7958   ret->setMeshDimension(meshDim);
7959   ret->setConnectivity(nodal,nodalIndex,true);
7960   ret->setCoords(coords);
7961   return ret;
7962 }
7963
7964 /*!
7965  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7966  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7967  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7968  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7969  * New" mode are returned for each input mesh.
7970  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7971  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7972  *          valid values [0,1,2], see zipConnectivityTraducer().
7973  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7974  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7975  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7976  *          no more needed.
7977  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7978  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7979  *          is no more needed.
7980  *  \throw If \a meshes.size() == 0.
7981  *  \throw If \a meshes[ *i* ] == NULL.
7982  *  \throw If the meshes do not share the node coordinates array.
7983  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7984  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7985  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7986  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7987  */
7988 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7989 {
7990   //All checks are delegated to MergeUMeshesOnSameCoords
7991   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7992   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7993   corr.resize(meshes.size());
7994   std::size_t nbOfMeshes=meshes.size();
7995   int offset=0;
7996   const int *o2nPtr=o2n->getConstPointer();
7997   for(std::size_t i=0;i<nbOfMeshes;i++)
7998     {
7999       DataArrayInt *tmp=DataArrayInt::New();
8000       int curNbOfCells=meshes[i]->getNumberOfCells();
8001       tmp->alloc(curNbOfCells,1);
8002       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8003       offset+=curNbOfCells;
8004       tmp->setName(meshes[i]->getName());
8005       corr[i]=tmp;
8006     }
8007   return ret.retn();
8008 }
8009
8010 /*!
8011  * Makes all given meshes share the nodal connectivity array. The common connectivity
8012  * array is created by concatenating the connectivity arrays of all given meshes. All
8013  * the given meshes must be of the same space dimension but dimension of cells **can
8014  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8015  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8016  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8017  *  \param [in,out] meshes - a vector of meshes to update.
8018  *  \throw If any of \a meshes is NULL.
8019  *  \throw If the coordinates array is not set in any of \a meshes.
8020  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8021  *  \throw If \a meshes are of different space dimension.
8022  */
8023 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8024 {
8025   std::size_t sz=meshes.size();
8026   if(sz==0 || sz==1)
8027     return;
8028   std::vector< const DataArrayDouble * > coords(meshes.size());
8029   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8030   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8031     {
8032       if((*it))
8033         {
8034           (*it)->checkConnectivityFullyDefined();
8035           const DataArrayDouble *coo=(*it)->getCoords();
8036           if(coo)
8037             *it2=coo;
8038           else
8039             {
8040               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8041               oss << " has no coordinate array defined !";
8042               throw INTERP_KERNEL::Exception(oss.str().c_str());
8043             }
8044         }
8045       else
8046         {
8047           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8048           oss << " is null !";
8049           throw INTERP_KERNEL::Exception(oss.str().c_str());
8050         }
8051     }
8052   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8053   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8054   int offset=(*it)->getNumberOfNodes();
8055   (*it++)->setCoords(res);
8056   for(;it!=meshes.end();it++)
8057     {
8058       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8059       (*it)->setCoords(res);
8060       (*it)->shiftNodeNumbersInConn(offset);
8061       offset+=oldNumberOfNodes;
8062     }
8063 }
8064
8065 /*!
8066  * Merges nodes coincident with a given precision within all given meshes that share
8067  * the nodal connectivity array. The given meshes **can be of different** mesh
8068  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8069  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8070  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8071  *  \param [in,out] meshes - a vector of meshes to update.
8072  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8073  *  \throw If any of \a meshes is NULL.
8074  *  \throw If the \a meshes do not share the same node coordinates array.
8075  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8076  */
8077 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8078 {
8079   if(meshes.empty())
8080     return ;
8081   std::set<const DataArrayDouble *> s;
8082   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8083     {
8084       if(*it)
8085         s.insert((*it)->getCoords());
8086       else
8087         {
8088           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 !";
8089           throw INTERP_KERNEL::Exception(oss.str().c_str());
8090         }
8091     }
8092   if(s.size()!=1)
8093     {
8094       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 !";
8095       throw INTERP_KERNEL::Exception(oss.str().c_str());
8096     }
8097   const DataArrayDouble *coo=*(s.begin());
8098   if(!coo)
8099     return;
8100   //
8101   DataArrayInt *comm,*commI;
8102   coo->findCommonTuples(eps,-1,comm,commI);
8103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8104   int oldNbOfNodes=coo->getNumberOfTuples();
8105   int newNbOfNodes;
8106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8107   if(oldNbOfNodes==newNbOfNodes)
8108     return ;
8109   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8110   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8111     {
8112       (*it)->renumberNodesInConn(o2n->getConstPointer());
8113       (*it)->setCoords(newCoords);
8114     } 
8115 }
8116
8117 /*!
8118  * 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.
8119  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8120  * \param isQuad specifies the policy of connectivity.
8121  * @ret in/out parameter in which the result will be append
8122  */
8123 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8124 {
8125   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8126   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8127   ret.push_back(cm.getExtrudedType());
8128   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8129   switch(flatType)
8130   {
8131     case INTERP_KERNEL::NORM_POINT1:
8132       {
8133         ret.push_back(connBg[1]);
8134         ret.push_back(connBg[1]+nbOfNodesPerLev);
8135         break;
8136       }
8137     case INTERP_KERNEL::NORM_SEG2:
8138       {
8139         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8140         ret.insert(ret.end(),conn,conn+4);
8141         break;
8142       }
8143     case INTERP_KERNEL::NORM_SEG3:
8144       {
8145         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8146         ret.insert(ret.end(),conn,conn+8);
8147         break;
8148       }
8149     case INTERP_KERNEL::NORM_QUAD4:
8150       {
8151         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8152         ret.insert(ret.end(),conn,conn+8);
8153         break;
8154       }
8155     case INTERP_KERNEL::NORM_TRI3:
8156       {
8157         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8158         ret.insert(ret.end(),conn,conn+6);
8159         break;
8160       }
8161     case INTERP_KERNEL::NORM_TRI6:
8162       {
8163         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,
8164           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8165         ret.insert(ret.end(),conn,conn+15);
8166         break;
8167       }
8168     case INTERP_KERNEL::NORM_QUAD8:
8169       {
8170         int conn[20]={
8171           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8172           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8173           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8174         };
8175         ret.insert(ret.end(),conn,conn+20);
8176         break;
8177       }
8178     case INTERP_KERNEL::NORM_POLYGON:
8179       {
8180         std::back_insert_iterator< std::vector<int> > ii(ret);
8181         std::copy(connBg+1,connEnd,ii);
8182         *ii++=-1;
8183         std::reverse_iterator<const int *> rConnBg(connEnd);
8184         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8185         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8186         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8187         for(std::size_t i=0;i<nbOfRadFaces;i++)
8188           {
8189             *ii++=-1;
8190             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8191             std::copy(conn,conn+4,ii);
8192           }
8193         break;
8194       }
8195     default:
8196       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8197   }
8198 }
8199
8200 /*!
8201  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8202  */
8203 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8204 {
8205   std::size_t i, ip1;
8206   double v[3]={0.,0.,0.};
8207   std::size_t sz=std::distance(begin,end);
8208   if(isQuadratic)
8209     sz/=2;
8210   for(i=0;i<sz;i++)
8211     {
8212       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];
8213       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8214       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8215     }
8216   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8217
8218   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8219   // SEG3 forming a circle):
8220   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8221     {
8222       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8223       for(std::size_t j=0;j<sz;j++)
8224         {
8225           if (j%2)  // current point i is quadratic, next point i+1 is standard
8226             {
8227               i = sz+j;
8228               ip1 = (j+1)%sz; // ip1 = "i+1"
8229             }
8230           else      // current point i is standard, next point i+1 is quadratic
8231             {
8232               i = j;
8233               ip1 = j+sz;
8234             }
8235           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8236           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8237           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8238         }
8239       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8240     }
8241   return (ret>0.);
8242 }
8243
8244 /*!
8245  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8246  */
8247 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8248 {
8249   std::vector<std::pair<int,int> > edges;
8250   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8251   const int *bgFace=begin;
8252   for(std::size_t i=0;i<nbOfFaces;i++)
8253     {
8254       const int *endFace=std::find(bgFace+1,end,-1);
8255       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8256       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8257         {
8258           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8259           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8260             return false;
8261           edges.push_back(p1);
8262         }
8263       bgFace=endFace+1;
8264     }
8265   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8266 }
8267
8268 /*!
8269  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8270  */
8271 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8272 {
8273   double vec0[3],vec1[3];
8274   std::size_t sz=std::distance(begin,end);
8275   if(sz%2!=0)
8276     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8277   int nbOfNodes=(int)sz/2;
8278   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8279   const double *pt0=coords+3*begin[0];
8280   const double *pt1=coords+3*begin[nbOfNodes];
8281   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8282   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8283 }
8284
8285 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8286 {
8287   std::size_t sz=std::distance(begin,end);
8288   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8289   std::size_t nbOfNodes(sz/2);
8290   std::copy(begin,end,(int *)tmp);
8291   for(std::size_t j=1;j<nbOfNodes;j++)
8292     {
8293       begin[j]=tmp[nbOfNodes-j];
8294       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8295     }
8296 }
8297
8298 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8299 {
8300   std::size_t sz=std::distance(begin,end);
8301   if(sz!=4)
8302     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8303   double vec0[3],vec1[3];
8304   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8305   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]; 
8306   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;
8307 }
8308
8309 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8310 {
8311   std::size_t sz=std::distance(begin,end);
8312   if(sz!=5)
8313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8314   double vec0[3];
8315   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8316   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8317   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8318 }
8319
8320 /*!
8321  * 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 ) 
8322  * 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
8323  * a 2D space.
8324  *
8325  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8326  * \param [in] coords the coordinates with nb of components exactly equal to 3
8327  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8328  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8329  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8330  */
8331 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8332 {
8333   int nbFaces=std::count(begin+1,end,-1)+1;
8334   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8335   double *vPtr=v->getPointer();
8336   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8337   double *pPtr=p->getPointer();
8338   const int *stFaceConn=begin+1;
8339   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8340     {
8341       const int *endFaceConn=std::find(stFaceConn,end,-1);
8342       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8343       stFaceConn=endFaceConn+1;
8344     }
8345   pPtr=p->getPointer(); vPtr=v->getPointer();
8346   DataArrayInt *comm1=0,*commI1=0;
8347   v->findCommonTuples(eps,-1,comm1,commI1);
8348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8349   const int *comm1Ptr=comm1->getConstPointer();
8350   const int *commI1Ptr=commI1->getConstPointer();
8351   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8352   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8353   //
8354   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8355   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8356   mm->finishInsertingCells();
8357   //
8358   for(int i=0;i<nbOfGrps1;i++)
8359     {
8360       int vecId=comm1Ptr[commI1Ptr[i]];
8361       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8362       DataArrayInt *comm2=0,*commI2=0;
8363       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8364       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8365       const int *comm2Ptr=comm2->getConstPointer();
8366       const int *commI2Ptr=commI2->getConstPointer();
8367       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8368       for(int j=0;j<nbOfGrps2;j++)
8369         {
8370           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8371             {
8372               res->insertAtTheEnd(begin,end);
8373               res->pushBackSilent(-1);
8374             }
8375           else
8376             {
8377               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8378               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8379               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8380               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8381               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8382               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8383               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8384               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8385               const int *idsNodePtr=idsNode->getConstPointer();
8386               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];
8387               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8388               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8389               if(std::abs(norm)>eps)
8390                 {
8391                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8392                   mm3->rotate(center,vec,angle);
8393                 }
8394               mm3->changeSpaceDimension(2);
8395               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8396               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8397               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8398               int nbOfCells=mm4->getNumberOfCells();
8399               for(int k=0;k<nbOfCells;k++)
8400                 {
8401                   int l=0;
8402                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8403                     res->pushBackSilent(idsNodePtr[*work]);
8404                   res->pushBackSilent(-1);
8405                 }
8406             }
8407         }
8408     }
8409   res->popBackSilent();
8410 }
8411
8412 /*!
8413  * 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
8414  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8415  * 
8416  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8417  * \param [in] coords coordinates expected to have 3 components.
8418  * \param [in] begin start of the nodal connectivity of the face.
8419  * \param [in] end end of the nodal connectivity (excluded) of the face.
8420  * \param [out] v the normalized vector of size 3
8421  * \param [out] p the pos of plane
8422  */
8423 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8424 {
8425   std::size_t nbPoints=std::distance(begin,end);
8426   if(nbPoints<3)
8427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8428   double vec[3]={0.,0.,0.};
8429   std::size_t j=0;
8430   bool refFound=false;
8431   for(;j<nbPoints-1 && !refFound;j++)
8432     {
8433       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8434       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8435       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8436       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8437       if(norm>eps)
8438         {
8439           refFound=true;
8440           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8441         }
8442     }
8443   for(std::size_t i=j;i<nbPoints-1;i++)
8444     {
8445       double curVec[3];
8446       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8447       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8448       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8449       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8450       if(norm<eps)
8451         continue;
8452       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8453       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];
8454       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8455       if(norm>eps)
8456         {
8457           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8458           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8459           return ;
8460         }
8461     }
8462   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8463 }
8464
8465 /*!
8466  * This method tries to obtain a well oriented polyhedron.
8467  * If the algorithm fails, an exception will be thrown.
8468  */
8469 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8470 {
8471   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8472   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8473   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8474   isPerm[0]=true;
8475   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8476   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8477   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8478   //
8479   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8480     {
8481       bgFace=begin;
8482       std::size_t smthChanged=0;
8483       for(std::size_t i=0;i<nbOfFaces;i++)
8484         {
8485           endFace=std::find(bgFace+1,end,-1);
8486           nbOfEdgesInFace=std::distance(bgFace,endFace);
8487           if(!isPerm[i])
8488             {
8489               bool b;
8490               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8491                 {
8492                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8493                   std::pair<int,int> p2(p1.second,p1.first);
8494                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8495                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8496                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8497                 }
8498               if(isPerm[i])
8499                 { 
8500                   if(!b)
8501                     std::reverse(bgFace+1,endFace);
8502                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8503                     {
8504                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8505                       std::pair<int,int> p2(p1.second,p1.first);
8506                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8507                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8508                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8509                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8510                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8511                       if(it!=edgesOK.end())
8512                         {
8513                           edgesOK.erase(it);
8514                           edgesFinished.push_back(p1);
8515                         }
8516                       else
8517                         edgesOK.push_back(p1);
8518                     }
8519                 }
8520             }
8521           bgFace=endFace+1;
8522         }
8523       if(smthChanged==0)
8524         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8525     }
8526   if(!edgesOK.empty())
8527     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8528   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8529     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8530       bgFace=begin;
8531       for(std::size_t i=0;i<nbOfFaces;i++)
8532         {
8533           endFace=std::find(bgFace+1,end,-1);
8534           std::reverse(bgFace+1,endFace);
8535           bgFace=endFace+1;
8536         }
8537     }
8538 }
8539
8540 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8541 {
8542   int nbOfNodesExpected(skin->getNumberOfNodes());
8543   const int *n2oPtr(n2o->getConstPointer());
8544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8545   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8546   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8547   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8548   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8549   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8550   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8551   if(nbOfNodesExpected<1)
8552     return ret.retn();
8553   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8554   *work++=n2oPtr[prevNode];
8555   for(int i=1;i<nbOfNodesExpected;i++)
8556     {
8557       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8558         {
8559           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8560           conn.erase(prevNode);
8561           if(conn.size()==1)
8562             {
8563               int curNode(*(conn.begin()));
8564               *work++=n2oPtr[curNode];
8565               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8566               shar.erase(prevCell);
8567               if(shar.size()==1)
8568                 {
8569                   prevCell=*(shar.begin());
8570                   prevNode=curNode;
8571                 }
8572               else
8573                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8574             }
8575           else
8576             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8577         }
8578       else
8579         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8580     }
8581   return ret.retn();
8582 }
8583
8584 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8585 {
8586   int nbOfNodesExpected(skin->getNumberOfNodes());
8587   int nbOfTurn(nbOfNodesExpected/2);
8588   const int *n2oPtr(n2o->getConstPointer());
8589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8590   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8591   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8592   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8593   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8594   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8595   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8596   if(nbOfNodesExpected<1)
8597     return ret.retn();
8598   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8599   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8600   for(int i=1;i<nbOfTurn;i++)
8601     {
8602       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8603         {
8604           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8605           conn.erase(prevNode);
8606           if(conn.size()==1)
8607             {
8608               int curNode(*(conn.begin()));
8609               *work=n2oPtr[curNode];
8610               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8611               shar.erase(prevCell);
8612               if(shar.size()==1)
8613                 {
8614                   int curCell(*(shar.begin()));
8615                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8616                   prevCell=curCell;
8617                   prevNode=curNode;
8618                   work++;
8619                 }
8620               else
8621                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8622             }
8623           else
8624             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8625         }
8626       else
8627         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8628     }
8629   return ret.retn();
8630 }
8631
8632 /*!
8633  * This method makes the assumption spacedimension == meshdimension == 2.
8634  * This method works only for linear cells.
8635  * 
8636  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8637  */
8638 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8639 {
8640   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8642   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8643   int oldNbOfNodes(skin->getNumberOfNodes());
8644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8645   int nbOfNodesExpected(skin->getNumberOfNodes());
8646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8647   int nbCells(skin->getNumberOfCells());
8648   if(nbCells==nbOfNodesExpected)
8649     return buildUnionOf2DMeshLinear(skin,n2o);
8650   else if(2*nbCells==nbOfNodesExpected)
8651     return buildUnionOf2DMeshQuadratic(skin,n2o);
8652   else
8653     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8654 }
8655
8656 /*!
8657  * This method makes the assumption spacedimension == meshdimension == 3.
8658  * This method works only for linear cells.
8659  * 
8660  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8661  */
8662 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8663 {
8664   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8665     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8666   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8667   const int *conn=m->getNodalConnectivity()->getConstPointer();
8668   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8669   int nbOfCells=m->getNumberOfCells();
8670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8671   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8672   if(nbOfCells<1)
8673     return ret.retn();
8674   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8675   for(int i=1;i<nbOfCells;i++)
8676     {
8677       *work++=-1;
8678       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8679     }
8680   return ret.retn();
8681 }
8682
8683 /*!
8684  * \brief Creates a graph of cell neighbors
8685  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8686  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8687  *  For example
8688  *  - index:  0 3 5 6 6
8689  *  - value:  1 2 3 2 3 3
8690  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8691  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8692  */
8693 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8694 {
8695   checkConnectivityFullyDefined();
8696
8697   int meshDim = this->getMeshDimension();
8698   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8699   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8700   this->getReverseNodalConnectivity(revConn,indexr);
8701   const int* indexr_ptr=indexr->getConstPointer();
8702   const int* revConn_ptr=revConn->getConstPointer();
8703
8704   const ParaMEDMEM::DataArrayInt* index;
8705   const ParaMEDMEM::DataArrayInt* conn;
8706   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8707   index=this->getNodalConnectivityIndex();
8708   int nbCells=this->getNumberOfCells();
8709   const int* index_ptr=index->getConstPointer();
8710   const int* conn_ptr=conn->getConstPointer();
8711
8712   //creating graph arcs (cell to cell relations)
8713   //arcs are stored in terms of (index,value) notation
8714   // 0 3 5 6 6
8715   // 1 2 3 2 3 3
8716   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8717   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8718
8719   //warning here one node have less than or equal effective number of cell with it
8720   //but cell could have more than effective nodes
8721   //because other equals nodes in other domain (with other global inode)
8722   std::vector <int> cell2cell_index(nbCells+1,0);
8723   std::vector <int> cell2cell;
8724   cell2cell.reserve(3*nbCells);
8725
8726   for (int icell=0; icell<nbCells;icell++)
8727     {
8728       std::map<int,int > counter;
8729       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8730         {
8731           int inode=conn_ptr[iconn];
8732           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8733             {
8734               int icell2=revConn_ptr[iconnr];
8735               std::map<int,int>::iterator iter=counter.find(icell2);
8736               if (iter!=counter.end()) (iter->second)++;
8737               else counter.insert(std::make_pair(icell2,1));
8738             }
8739         }
8740       for (std::map<int,int>::const_iterator iter=counter.begin();
8741            iter!=counter.end(); iter++)
8742         if (iter->second >= meshDim)
8743           {
8744             cell2cell_index[icell+1]++;
8745             cell2cell.push_back(iter->first);
8746           }
8747     }
8748   indexr->decrRef();
8749   revConn->decrRef();
8750   cell2cell_index[0]=0;
8751   for (int icell=0; icell<nbCells;icell++)
8752     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8753
8754   //filling up index and value to create skylinearray structure
8755   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8756   return array;
8757 }
8758
8759 /*!
8760  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8761  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8762  */
8763 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8764 {
8765   double *w=zipFrmt;
8766   if(spaceDim==3)
8767     for(int i=0;i<nbOfNodesInCell;i++)
8768       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8769   else if(spaceDim==2)
8770     {
8771       for(int i=0;i<nbOfNodesInCell;i++)
8772         {
8773           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8774           *w++=0.;
8775         }
8776     }
8777   else
8778     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8779 }
8780
8781 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8782 {
8783   int nbOfCells=getNumberOfCells();
8784   if(nbOfCells<=0)
8785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8786   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};
8787   ofs << "  <" << getVTKDataSetType() << ">\n";
8788   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8789   ofs << "      <PointData>\n" << pointData << std::endl;
8790   ofs << "      </PointData>\n";
8791   ofs << "      <CellData>\n" << cellData << std::endl;
8792   ofs << "      </CellData>\n";
8793   ofs << "      <Points>\n";
8794   if(getSpaceDimension()==3)
8795     _coords->writeVTK(ofs,8,"Points",byteData);
8796   else
8797     {
8798       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8799       coo->writeVTK(ofs,8,"Points",byteData);
8800     }
8801   ofs << "      </Points>\n";
8802   ofs << "      <Cells>\n";
8803   const int *cPtr=_nodal_connec->getConstPointer();
8804   const int *cIPtr=_nodal_connec_index->getConstPointer();
8805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8806   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8809   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8810   int szFaceOffsets=0,szConn=0;
8811   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8812     {
8813       *w2=cPtr[cIPtr[i]];
8814       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8815         {
8816           *w1=-1;
8817           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8818           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8819         }
8820       else
8821         {
8822           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8823           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8824           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8825           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8826           w4=std::copy(c.begin(),c.end(),w4);
8827         }
8828     }
8829   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8830   types->writeVTK(ofs,8,"UInt8","types",byteData);
8831   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8832   if(szFaceOffsets!=0)
8833     {//presence of Polyhedra
8834       connectivity->reAlloc(szConn);
8835       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8836       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8837       w1=faces->getPointer();
8838       for(int i=0;i<nbOfCells;i++)
8839         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8840           {
8841             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8842             *w1++=nbFaces;
8843             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8844             for(int j=0;j<nbFaces;j++)
8845               {
8846                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8847                 *w1++=(int)std::distance(w6,w5);
8848                 w1=std::copy(w6,w5,w1);
8849                 w6=w5+1;
8850               }
8851           }
8852       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8853     }
8854   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8855   ofs << "      </Cells>\n";
8856   ofs << "    </Piece>\n";
8857   ofs << "  </" << getVTKDataSetType() << ">\n";
8858 }
8859
8860 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8861 {
8862   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8863   if(_mesh_dim==-2)
8864     { stream << " Not set !"; return ; }
8865   stream << " Mesh dimension : " << _mesh_dim << ".";
8866   if(_mesh_dim==-1)
8867     return ;
8868   if(!_coords)
8869     { stream << " No coordinates set !"; return ; }
8870   if(!_coords->isAllocated())
8871     { stream << " Coordinates set but not allocated !"; return ; }
8872   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8873   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8874   if(!_nodal_connec_index)
8875     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8876   if(!_nodal_connec_index->isAllocated())
8877     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8878   int lgth=_nodal_connec_index->getNumberOfTuples();
8879   int cpt=_nodal_connec_index->getNumberOfComponents();
8880   if(cpt!=1 || lgth<1)
8881     return ;
8882   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8883 }
8884
8885 std::string MEDCouplingUMesh::getVTKDataSetType() const
8886 {
8887   return std::string("UnstructuredGrid");
8888 }
8889
8890 std::string MEDCouplingUMesh::getVTKFileExtension() const
8891 {
8892   return std::string("vtu");
8893 }
8894
8895 /*!
8896  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8897  * returns a result mesh constituted by polygons.
8898  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8899  * all nodes from m2.
8900  * The meshes should be in 2D space. In
8901  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8902  * meshes.
8903  *  \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
8904  *                      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)
8905  *  \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
8906  *                      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)
8907  *  \param [in] eps - precision used to detect coincident mesh entities.
8908  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8909  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8910  *         this array using decrRef() as it is no more needed.
8911  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8912  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8913  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8914  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8915  *         it is no more needed.  
8916  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8917  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8918  *         is no more needed.  
8919  *  \throw If the coordinates array is not set in any of the meshes.
8920  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8921  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8922  *
8923  *  \sa conformize2D, mergeNodes
8924  */
8925 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8926                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8927 {
8928   if(!m1 || !m2)
8929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8930   m1->checkFullyDefined();
8931   m2->checkFullyDefined();
8932   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8934
8935   // Step 1: compute all edge intersections (new nodes)
8936   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8937   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8938   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8939   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8940   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8941                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8942                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8943   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8944   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8945   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8946
8947   // Step 2: re-order newly created nodes according to the ordering found in m2
8948   std::vector< std::vector<int> > intersectEdge2;
8949   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8950   subDiv2.clear(); dd5=0; dd6=0;
8951
8952   // Step 3:
8953   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8954   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8955   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8956                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8957
8958   // Step 4: Prepare final result:
8959   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8960   addCooDa->alloc((int)(addCoo.size())/2,2);
8961   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8962   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8963   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8964   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8965   std::vector<const DataArrayDouble *> coordss(4);
8966   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8967   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8968   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8971   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8973   ret->setConnectivity(conn,connI,true);
8974   ret->setCoords(coo);
8975   cellNb1=c1.retn(); cellNb2=c2.retn();
8976   return ret.retn();
8977 }
8978
8979 /// @cond INTERNAL
8980
8981 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8982 {
8983   if(candidates.empty())
8984     return false;
8985   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8986     {
8987       const std::vector<int>& pool(intersectEdge1[*it]);
8988       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8989       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8990         {
8991           retVal=*it+1;
8992           return true;
8993         }
8994       tmp[0]=stop; tmp[1]=start;
8995       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8996         {
8997           retVal=-*it-1;
8998           return true;
8999         }
9000     }
9001   return false;
9002 }
9003
9004 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,
9005                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9006 {
9007   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9008   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9009   int nCells(mesh1D->getNumberOfCells());
9010   if(nCells!=(int)intersectEdge2.size())
9011     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9012   const DataArrayDouble *coo2(mesh1D->getCoords());
9013   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9014   const double *coo2Ptr(coo2->begin());
9015   int offset1(coords1->getNumberOfTuples());
9016   int offset2(offset1+coo2->getNumberOfTuples());
9017   int offset3(offset2+addCoo.size()/2);
9018   std::vector<double> addCooQuad;
9019   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9020   int tmp[4],cicnt(0),kk(0);
9021   for(int i=0;i<nCells;i++)
9022     {
9023       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9024       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9025       const std::vector<int>& subEdges(intersectEdge2[i]);
9026       int nbSubEdge(subEdges.size()/2);
9027       for(int j=0;j<nbSubEdge;j++,kk++)
9028         {
9029           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
9030           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9031           INTERP_KERNEL::Edge *e2Ptr(e2);
9032           std::map<int,int>::const_iterator itm;
9033           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9034             {
9035               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9036               itm=mergedNodes.find(subEdges[2*j]);
9037               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9038               itm=mergedNodes.find(subEdges[2*j+1]);
9039               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9040               tmp[3]=offset3+(int)addCooQuad.size()/2;
9041               double tmp2[2];
9042               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9043               cicnt+=4;
9044               cOut->insertAtTheEnd(tmp,tmp+4);
9045               ciOut->pushBackSilent(cicnt);
9046             }
9047           else
9048             {
9049               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9050               itm=mergedNodes.find(subEdges[2*j]);
9051               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9052               itm=mergedNodes.find(subEdges[2*j+1]);
9053               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9054               cicnt+=3;
9055               cOut->insertAtTheEnd(tmp,tmp+3);
9056               ciOut->pushBackSilent(cicnt);
9057             }
9058           int tmp00;
9059           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9060             {
9061               idsInRetColinear->pushBackSilent(kk);
9062               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9063             }
9064         }
9065       e->decrRef();
9066     }
9067   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9068   ret->setConnectivity(cOut,ciOut,true);
9069   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9070   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9071   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9072   std::vector<const DataArrayDouble *> coordss(4);
9073   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9074   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9075   ret->setCoords(arr);
9076   return ret.retn();
9077 }
9078
9079 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9080 {
9081   std::vector<int> allEdges;
9082   for(const int *it2(descBg);it2!=descEnd;it2++)
9083     {
9084       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9085       if(*it2>0)
9086         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9087       else
9088         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9089     }
9090   std::size_t nb(allEdges.size());
9091   if(nb%2!=0)
9092     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9093   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9094   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9095   ret->setCoords(coords);
9096   ret->allocateCells(1);
9097   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9098   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9099     connOut[kk]=allEdges[2*kk];
9100   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9101   return ret.retn();
9102 }
9103
9104 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9105 {
9106   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9107   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9108   std::size_t ii(0);
9109   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9110   if(sz!=std::distance(descBg,descEnd))
9111     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9112   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9113   std::vector<int> allEdges,centers;
9114   const double *coordsPtr(coords->begin());
9115   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9116   int offset(coords->getNumberOfTuples());
9117   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9118     {
9119       INTERP_KERNEL::NormalizedCellType typeOfSon;
9120       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9121       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9122       if(*it2>0)
9123         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9124       else
9125         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9126       if(edge1.size()==2)
9127         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9128       else
9129         {//the current edge has been subsplit -> create corresponding centers.
9130           std::size_t nbOfCentersToAppend(edge1.size()/2);
9131           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9132           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9133           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9134           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9135             {
9136               double tmpp[2];
9137               const double *aa(coordsPtr+2*(*it3++));
9138               const double *bb(coordsPtr+2*(*it3++));
9139               ee->getMiddleOfPoints(aa,bb,tmpp);
9140               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9141               centers.push_back(offset+k);
9142             }
9143         }
9144     }
9145   std::size_t nb(allEdges.size());
9146   if(nb%2!=0)
9147     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9148   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9149   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9150   if(addCoo->empty())
9151     ret->setCoords(coords);
9152   else
9153     {
9154       addCoo->rearrange(2);
9155       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9156       ret->setCoords(addCoo);
9157     }
9158   ret->allocateCells(1);
9159   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9160   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9161     connOut[kk]=allEdges[2*kk];
9162   connOut.insert(connOut.end(),centers.begin(),centers.end());
9163   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9164   return ret.retn();
9165 }
9166
9167 /*!
9168  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9169  * of those edges.
9170  *
9171  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9172  */
9173 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9174 {
9175   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9176   if(!cm.isQuadratic())
9177     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9178   else
9179     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9180 }
9181
9182 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9183 {
9184   bool isQuad(false);
9185   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9186     {
9187       const INTERP_KERNEL::Edge *ee(*it);
9188       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9189         isQuad=true;
9190     }
9191   if(!isQuad)
9192     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9193   else
9194     {
9195       const double *coo(mesh2D->getCoords()->begin());
9196       std::size_t sz(conn.size());
9197       std::vector<double> addCoo;
9198       std::vector<int> conn2(conn);
9199       int offset(mesh2D->getNumberOfNodes());
9200       for(std::size_t i=0;i<sz;i++)
9201         {
9202           double tmp[2];
9203           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9204           addCoo.insert(addCoo.end(),tmp,tmp+2);
9205           conn2.push_back(offset+(int)i);
9206         }
9207       mesh2D->getCoords()->rearrange(1);
9208       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9209       mesh2D->getCoords()->rearrange(2);
9210       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9211     }
9212 }
9213
9214 /*!
9215  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9216  *
9217  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9218  * a set of edges defined in \a splitMesh1D.
9219  */
9220 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9221                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9222 {
9223   std::size_t nb(edge1Bis.size()/2);
9224   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9225   int iEnd(splitMesh1D->getNumberOfCells());
9226   if(iEnd==0)
9227     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9228   std::size_t ii,jj;
9229   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9230   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9231   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9232   //
9233   if(jj==nb)
9234     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9235       out0.resize(1); out1.resize(1);
9236       std::vector<int>& connOut(out0[0]);
9237       connOut.resize(nbOfEdgesOf2DCellSplit);
9238       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9239       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9240       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9241         {
9242           connOut[kk]=edge1Bis[2*kk];
9243           edgesPtr[kk]=edge1BisPtr[2*kk];
9244         }
9245     }
9246   else
9247     {
9248       // [i,iEnd[ contains the
9249       out0.resize(2); out1.resize(2);
9250       std::vector<int>& connOutLeft(out0[0]);
9251       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9252       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9253       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9254       for(std::size_t k=ii;k<jj+1;k++)
9255         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9256       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9257       for(int ik=0;ik<iEnd;ik++)
9258         {
9259           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9260           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9261           ees[ik]=ee;
9262         }
9263       for(int ik=iEnd-1;ik>=0;ik--)
9264         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9265       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9266         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9267       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9268       for(int ik=0;ik<iEnd;ik++)
9269         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9270       eright.insert(eright.end(),ees.begin(),ees.end());
9271     }
9272 }
9273
9274 /// @endcond
9275
9276 /// @cond INTERNAL
9277
9278 struct CellInfo
9279 {
9280 public:
9281   CellInfo() { }
9282   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9283 public:
9284   std::vector<int> _edges;
9285   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9286 };
9287
9288 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9289 {
9290   std::size_t nbe(edges.size());
9291   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9292   for(std::size_t i=0;i<nbe;i++)
9293     {
9294       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9295       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9296     }
9297   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9298   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9299   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9300 }
9301
9302 class EdgeInfo
9303 {
9304 public:
9305   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9306   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9307   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9308   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9309   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9310 private:
9311   int _istart;
9312   int _iend;
9313   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9314   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9315   int _left;
9316   int _right;
9317 };
9318
9319 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9320 {
9321   const MEDCouplingUMesh *mesh(_mesh);
9322   if(mesh)
9323     return ;
9324   if(_right<pos)
9325     return ;
9326   if(_left>pos)
9327     { _left++; _right++; return ; }
9328   if(_right==pos)
9329     {
9330       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9331       if((isLeft && isRight) || (!isLeft && !isRight))
9332         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9333       if(isLeft)
9334         return ;
9335       if(isRight)
9336         {
9337           _right++;
9338           return ;
9339         }
9340     }
9341   if(_left==pos)
9342     {
9343       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9344       if((isLeft && isRight) || (!isLeft && !isRight))
9345         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9346       if(isLeft)
9347         {
9348           _right++;
9349           return ;
9350         }
9351       if(isRight)
9352         {
9353           _left++;
9354           _right++;
9355           return ;
9356         }
9357     }
9358 }
9359
9360 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9361 {
9362   const MEDCouplingUMesh *mesh(_mesh);
9363   if(!mesh)
9364     {
9365       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9366     }
9367   else
9368     {// not fully splitting cell case
9369       if(mesh2D->getNumberOfCells()==1)
9370         {//little optimization. 1 cell no need to find in which cell mesh is !
9371           neighbors[0]=offset; neighbors[1]=offset;
9372           return;
9373         }
9374       else
9375         {
9376           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9377           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9378           if(cellId==-1)
9379             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9380           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9381         }
9382     }
9383 }
9384
9385 class VectorOfCellInfo
9386 {
9387 public:
9388   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9389   std::size_t size() const { return _pool.size(); }
9390   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9391   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9392   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9393   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9395   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9396 private:
9397   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9398   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9399   const CellInfo& get(int pos) const;
9400   CellInfo& get(int pos);
9401 private:
9402   std::vector<CellInfo> _pool;
9403   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9404   std::vector<EdgeInfo> _edge_info;
9405 };
9406
9407 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9408 {
9409   _pool[0]._edges=edges;
9410   _pool[0]._edges_ptr=edgesPtr;
9411 }
9412
9413 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9414 {
9415   if(_pool.empty())
9416     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9417   if(_pool.size()==1)
9418     return 0;
9419   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9420   if(!zeMesh)
9421     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9422   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9423   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9424 }
9425
9426 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9427 {
9428   get(pos);//to check pos
9429   bool isFast(pos==0 && _pool.size()==1);
9430   std::size_t sz(edges.size());
9431   // dealing with edges
9432   if(sz==1)
9433     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9434   else
9435     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9436   //
9437   std::vector<CellInfo> pool(_pool.size()-1+sz);
9438   for(int i=0;i<pos;i++)
9439     pool[i]=_pool[i];
9440   for(std::size_t j=0;j<sz;j++)
9441     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9442   for(int i=pos+1;i<(int)_pool.size();i++)
9443     pool[i+sz-1]=_pool[i];
9444   _pool=pool;
9445   //
9446   if(sz==2)
9447     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9448   //
9449   if(isFast)
9450     {
9451       _ze_mesh=mesh;
9452       return ;
9453     }
9454   //
9455   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9456   if(pos>0)
9457     {
9458       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9459       ms.push_back(elt);
9460     }
9461   ms.push_back(mesh);
9462   if(pos<_ze_mesh->getNumberOfCells()-1)
9463   {
9464     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9465     ms.push_back(elt);
9466   }
9467   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9468   for(std::size_t j=0;j<ms2.size();j++)
9469     ms2[j]=ms[j];
9470   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9471 }
9472
9473 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9474 {
9475   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9476 }
9477
9478 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9479 {
9480   if(pos<0)
9481     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9482   int ret(0);
9483   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9484     {
9485       if((*it).isInMyRange(pos))
9486         return ret;
9487     }
9488   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9489 }
9490
9491 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9492 {
9493   get(pos);//to check;
9494   if(_edge_info.empty())
9495     return ;
9496   std::size_t sz(_edge_info.size()-1);
9497   for(std::size_t i=0;i<sz;i++)
9498     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9499 }
9500
9501 const CellInfo& VectorOfCellInfo::get(int pos) const
9502 {
9503   if(pos<0 || pos>=(int)_pool.size())
9504     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9505   return _pool[pos];
9506 }
9507
9508 CellInfo& VectorOfCellInfo::get(int pos)
9509 {
9510   if(pos<0 || pos>=(int)_pool.size())
9511     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9512   return _pool[pos];
9513 }
9514
9515 /*!
9516  * Given :
9517  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9518  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9519  *
9520  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9521  *
9522  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9523  *
9524  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9525  */
9526 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9527                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9528 {
9529   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9530   if(nbCellsInSplitMesh1D==0)
9531     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9532   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9533   std::size_t nb(allEdges.size()),jj;
9534   if(nb%2!=0)
9535     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9536   std::vector<int> edge1Bis(nb*2);
9537   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9538   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9539   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9540   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9541   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9542   //
9543   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9544   int *idsLeftRightPtr(idsLeftRight->getPointer());
9545   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9546   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9547     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9548       int iEnd(iStart);
9549       for(;iEnd<nbCellsInSplitMesh1D;)
9550         {
9551           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9552           if(jj!=nb)
9553             break;
9554           else
9555             iEnd++;
9556         }
9557       if(iEnd<nbCellsInSplitMesh1D)
9558         iEnd++;
9559       //
9560       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9561       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9562       //
9563       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9564       retTmp->setCoords(splitMesh1D->getCoords());
9565       retTmp->allocateCells();
9566
9567       std::vector< std::vector<int> > out0;
9568       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9569
9570       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9571       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9572         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9573       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9574       //
9575       iStart=iEnd;
9576     }
9577   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9578     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9579   return pool.getZeMesh().retn();
9580 }
9581
9582 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9583                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9584                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9585 {
9586   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9587   //
9588   std::vector<int> allEdges;
9589   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9590   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9591     {
9592       int edgeId(std::abs(*it)-1);
9593       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9594       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9595       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9596       if(*it>0)
9597         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9598       else
9599         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9600       std::size_t sz(edge1.size());
9601       for(std::size_t cnt=0;cnt<sz;cnt++)
9602         allEdgesPtr.push_back(ee);
9603     }
9604   //
9605   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9606 }
9607
9608 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9609 {
9610   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9611     {//easy case comparison not
9612       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9613     }
9614   else if(typ1.isQuadratic() && typ2.isQuadratic())
9615     {
9616       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9617       if(!status0)
9618         return false;
9619       if(conn1[2]==conn2[2])
9620         return true;
9621       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9622       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9623       return dist<eps;
9624     }
9625   else
9626     {//only one is quadratic
9627       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9628       if(!status0)
9629         return false;
9630       const double *a(0),*bb(0),*be(0);
9631       if(typ1.isQuadratic())
9632         {
9633           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9634         }
9635       else
9636         {
9637           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9638         }
9639       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9640       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9641       return dist<eps;
9642     }
9643 }
9644
9645 /*!
9646  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9647  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9648  *
9649  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9650  */
9651 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9652 {
9653   if(candidatesIn2DEnd==candidatesIn2DBg)
9654     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9655   const double *coo(mesh2DSplit->getCoords()->begin());
9656   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9657     return *candidatesIn2DBg;
9658   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9659   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9660   if(cellIdInMesh1DSplitRelative<0)
9661     cur1D->changeOrientationOfCells();
9662   const int *c1D(cur1D->getNodalConnectivity()->begin());
9663   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9664   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9665     {
9666       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9667       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9668       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9669       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9670       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9671       for(unsigned it2=0;it2<sz;it2++)
9672         {
9673           INTERP_KERNEL::NormalizedCellType typeOfSon;
9674           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9675           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9676           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9677             return *it;
9678         }
9679     }
9680   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9681 }
9682
9683 /// @endcond
9684
9685 /*!
9686  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9687  * 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
9688  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9689  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9690  *
9691  * \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
9692  *                      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)
9693  * \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
9694  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9695  * \param [in] eps - precision used to perform intersections and localization operations.
9696  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9697  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9698  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9699  *                               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.
9700  * \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
9701  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9702  *                               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.
9703  *
9704  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9705  */
9706 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9707 {
9708   if(!mesh2D || !mesh1D)
9709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9710   mesh2D->checkFullyDefined();
9711   mesh1D->checkFullyDefined();
9712   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9713   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9714     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9715   // Step 1: compute all edge intersections (new nodes)
9716   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9717   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9718   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9719   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9720   //
9721   // Build desc connectivity
9722   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9723   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9724   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9725   std::map<int,int> mergedNodes;
9726   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9727   // use mergeNodes to fix intersectEdge1
9728   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9729     {
9730       std::size_t n((*it0).size()/2);
9731       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9732       std::map<int,int>::const_iterator it1;
9733       it1=mergedNodes.find(eltStart);
9734       if(it1!=mergedNodes.end())
9735         (*it0)[0]=(*it1).second;
9736       it1=mergedNodes.find(eltEnd);
9737       if(it1!=mergedNodes.end())
9738         (*it0)[2*n-1]=(*it1).second;
9739     }
9740   //
9741   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9742   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9743   // Step 2: re-order newly created nodes according to the ordering found in m2
9744   std::vector< std::vector<int> > intersectEdge2;
9745   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9746   subDiv2.clear();
9747   // Step 3: compute splitMesh1D
9748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9750   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9751       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9754   // deal with cells in mesh2D that are not cut but only some of their edges are
9755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9756   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9757   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9759   if(!idsInDesc2DToBeRefined->empty())
9760     {
9761       DataArrayInt *out0(0),*outi0(0);
9762       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9763       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9764       out0s=out0;
9765       out0s=out0s->buildUnique();
9766       out0s->sort(true);
9767     }
9768   //
9769   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9770   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9771   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9772   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9773   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9775   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9776     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9778   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9779   if((DataArrayInt *)out0s)
9780     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9781   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9782   // OK all is ready to insert in ret2 mesh
9783   if(!untouchedCells->empty())
9784     {// the most easy part, cells in mesh2D not impacted at all
9785       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9786       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9787       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9788     }
9789   if((DataArrayInt *)out0s)
9790     {// here dealing with cells in out0s but not in cellsToBeModified
9791       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9792       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9793       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9794         {
9795           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9796           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9797         }
9798       int offset(ret2->getNumberOfTuples());
9799       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9800       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9801       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9802       int kk(0),*ret3ptr(partOfRet3->getPointer());
9803       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9804         {
9805           int faceId(std::abs(*it)-1);
9806           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9807             {
9808               int tmp(fewModifiedCells->locateValue(*it2));
9809               if(tmp!=-1)
9810                 {
9811                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9812                     ret3ptr[2*kk]=tmp+offset;
9813                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9814                     ret3ptr[2*kk+1]=tmp+offset;
9815                 }
9816               else
9817                 {//the current edge is shared by a 2D cell that will be split just after
9818                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9819                     ret3ptr[2*kk]=-(*it2+1);
9820                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9821                     ret3ptr[2*kk+1]=-(*it2+1);
9822                 }
9823             }
9824         }
9825       m1Desc->setCoords(ret1->getCoords());
9826       ret1NonCol->setCoords(ret1->getCoords());
9827       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9828       if(!outMesh2DSplit.empty())
9829         {
9830           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9831           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9832             (*itt)->setCoords(da);
9833         }
9834     }
9835   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9836   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9837     {
9838       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9839       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9840       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9841       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9842       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9843       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9844       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9845       outMesh2DSplit.push_back(splitOfOneCell);
9846       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9847         ret2->pushBackSilent(*it);
9848     }
9849   //
9850   std::size_t nbOfMeshes(outMesh2DSplit.size());
9851   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9852   for(std::size_t i=0;i<nbOfMeshes;i++)
9853     tmp[i]=outMesh2DSplit[i];
9854   //
9855   ret1->getCoords()->setInfoOnComponents(compNames);
9856   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9857   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9858   ret3->rearrange(1);
9859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9860   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9861     {
9862       int old2DCellId(-ret3->getIJ(*it,0)-1);
9863       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9864       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
9865     }
9866   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9867   ret3->rearrange(2);
9868   //
9869   splitMesh1D=ret1.retn();
9870   splitMesh2D=ret2D.retn();
9871   cellIdInMesh2D=ret2.retn();
9872   cellIdInMesh1D=ret3.retn();
9873 }
9874
9875 /**
9876  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9877  * (newly created) nodes corresponding to the edge intersections.
9878  * Output params:
9879  * @param[out] cr, crI connectivity of the resulting mesh
9880  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9881  * TODO: describe input parameters
9882  */
9883 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9884                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9885                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9886                                                          const std::vector<double>& addCoords,
9887                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9888 {
9889   static const int SPACEDIM=2;
9890   const double *coo1(m1->getCoords()->getConstPointer());
9891   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9892   int offset1(m1->getNumberOfNodes());
9893   const double *coo2(m2->getCoords()->getConstPointer());
9894   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9895   int offset2(offset1+m2->getNumberOfNodes());
9896   int offset3(offset2+((int)addCoords.size())/2);
9897   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9898   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9899   // Here a BBTree on 2D-cells, not on segments:
9900   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9901   int ncell1(m1->getNumberOfCells());
9902   crI.push_back(0);
9903   for(int i=0;i<ncell1;i++)
9904     {
9905       std::vector<int> candidates2;
9906       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9907       std::map<INTERP_KERNEL::Node *,int> mapp;
9908       std::map<int,INTERP_KERNEL::Node *> mappRev;
9909       INTERP_KERNEL::QuadraticPolygon pol1;
9910       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9911       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9912       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9913       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9914       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9915       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9916           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9917       //
9918       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
9919       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9920       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9921       for(it1.first();!it1.finished();it1.next())
9922         edges1.insert(it1.current()->getPtr());
9923       //
9924       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9925       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9926       int ii=0;
9927       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9928         {
9929           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9930           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9931           // Complete mapping with elements coming from the current cell it2 in mesh2:
9932           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9933           // pol2 is the new QP in the final merged result.
9934           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9935               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9936         }
9937       ii=0;
9938       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9939         {
9940           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9941           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9942           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9943           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9944         }
9945       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9946       // by m2 but that we still want to keep in the final result.
9947       if(!edges1.empty())
9948         {
9949           try
9950           {
9951               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9952           }
9953           catch(INTERP_KERNEL::Exception& e)
9954           {
9955               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();
9956               throw INTERP_KERNEL::Exception(oss.str().c_str());
9957           }
9958         }
9959       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9960         (*it).second->decrRef();
9961     }
9962 }
9963
9964 /**
9965  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9966  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9967  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9968  * The caller is to deal with the resulting DataArrayInt.
9969  *  \throw If the coordinate array is not set.
9970  *  \throw If the nodal connectivity of the cells is not defined.
9971  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9972  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9973  *
9974  * \sa DataArrayInt::sortEachPairToMakeALinkedList
9975  */
9976 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9977 {
9978   checkFullyDefined();
9979   if(getMeshDimension()!=1)
9980     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9981
9982   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9985   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9986   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9987   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9989   const int * dsi(_dsi->getConstPointer());
9990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9991   m_points=0;
9992   if (dsii->getNumberOfTuples())
9993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9994
9995   int nc(getNumberOfCells());
9996   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9997   result->alloc(nc,1);
9998
9999   // set of edges not used so far
10000   std::set<int> edgeSet;
10001   for (int i=0; i<nc; edgeSet.insert(i), i++);
10002
10003   int startSeg=0;
10004   int newIdx=0;
10005   // while we have points with only one neighbor segments
10006   do
10007     {
10008       std::list<int> linePiece;
10009       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10010       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10011         {
10012           // Fill the list forward (resp. backward) from the start segment:
10013           int activeSeg = startSeg;
10014           int prevPointId = -20;
10015           int ptId;
10016           while (!edgeSet.empty())
10017             {
10018               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10019                 {
10020                   if (direction==0)
10021                     linePiece.push_back(activeSeg);
10022                   else
10023                     linePiece.push_front(activeSeg);
10024                   edgeSet.erase(activeSeg);
10025                 }
10026
10027               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10028               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10029               if (dsi[ptId] == 1) // hitting the end of the line
10030                 break;
10031               prevPointId = ptId;
10032               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10033               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10034             }
10035         }
10036       // Done, save final piece into DA:
10037       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10038       newIdx += linePiece.size();
10039
10040       // identify next valid start segment (one which is not consumed)
10041       if(!edgeSet.empty())
10042         startSeg = *(edgeSet.begin());
10043     }
10044   while (!edgeSet.empty());
10045   return result.retn();
10046 }
10047
10048 /// @cond INTERNAL
10049
10050 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10051 {
10052   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10053   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10054   if(it==m.end())
10055     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10056   int v((*it).second);
10057   if(v==forbVal0 || v==forbVal1)
10058     return ;
10059   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10060     isect.push_back(v);
10061 }
10062
10063 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10064 {
10065   int sz(c.size());
10066   if(sz<=1)
10067     return false;
10068   bool presenceOfOn(false);
10069   for(int i=0;i<sz;i++)
10070     {
10071       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10072       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10073         continue ;
10074       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10075       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10076     }
10077   return presenceOfOn;
10078 }
10079
10080 /// @endcond
10081
10082 /**
10083  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
10084  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
10085  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
10086  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10087  *
10088  * \return int - the number of new nodes created (in most of cases 0).
10089  * 
10090  * \throw If \a this is not coherent.
10091  * \throw If \a this has not spaceDim equal to 2.
10092  * \throw If \a this has not meshDim equal to 2.
10093  * \throw If some subcells needed to be split are orphan.
10094  * \sa MEDCouplingUMesh::conformize2D
10095  */
10096 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10097 {
10098   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10099     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10100   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10101   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10103   if(midOpt==0 && midOptI==0)
10104     {
10105       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10106       return 0;
10107     }
10108   else if(midOpt!=0 && midOptI!=0)
10109     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10110   else
10111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10112 }
10113
10114 /*!
10115  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10116  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10117  * 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
10118  * 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).
10119  * 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.
10120  * 
10121  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10122  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10123  *
10124  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10125  * This method expects that all nodes in \a this are not closer than \a eps.
10126  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10127  * 
10128  * \param [in] eps the relative error to detect merged edges.
10129  * \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
10130  *                           that the user is expected to deal with.
10131  *
10132  * \throw If \a this is not coherent.
10133  * \throw If \a this has not spaceDim equal to 2.
10134  * \throw If \a this has not meshDim equal to 2.
10135  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10136  */
10137 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10138 {
10139   static const int SPACEDIM=2;
10140   checkCoherency();
10141   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10143   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10144   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10145   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10146   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10147   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10148   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10149   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10150   std::vector<double> addCoo;
10151   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10152   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10153   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10154   for(int i=0;i<nDescCell;i++)
10155     {
10156       std::vector<int> candidates;
10157       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10158       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10159         if(*it>i)
10160           {
10161             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10162             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10163                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10164             INTERP_KERNEL::MergePoints merge;
10165             INTERP_KERNEL::QuadraticPolygon c1,c2;
10166             e1->intersectWith(e2,merge,c1,c2);
10167             e1->decrRef(); e2->decrRef();
10168             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10169               overlapEdge[i].push_back(*it);
10170             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10171               overlapEdge[*it].push_back(i);
10172           }
10173     }
10174   // splitting done. sort intersect point in intersectEdge.
10175   std::vector< std::vector<int> > middle(nDescCell);
10176   int nbOf2DCellsToBeSplit(0);
10177   bool middleNeedsToBeUsed(false);
10178   std::vector<bool> cells2DToTreat(nDescCell,false);
10179   for(int i=0;i<nDescCell;i++)
10180     {
10181       std::vector<int>& isect(intersectEdge[i]);
10182       int sz((int)isect.size());
10183       if(sz>1)
10184         {
10185           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10186           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10187           e->sortSubNodesAbs(coords,isect);
10188           e->decrRef();
10189         }
10190       if(sz!=0)
10191         {
10192           int idx0(rdi[i]),idx1(rdi[i+1]);
10193           if(idx1-idx0!=1)
10194             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10195           if(!cells2DToTreat[rd[idx0]])
10196             {
10197               cells2DToTreat[rd[idx0]]=true;
10198               nbOf2DCellsToBeSplit++;
10199             }
10200           // try to reuse at most eventual 'middle' of SEG3
10201           std::vector<int>& mid(middle[i]);
10202           mid.resize(sz+1,-1);
10203           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10204             {
10205               middleNeedsToBeUsed=true;
10206               const std::vector<int>& candidates(overlapEdge[i]);
10207               std::vector<int> trueCandidates;
10208               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10209                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10210                   trueCandidates.push_back(*itc);
10211               int stNode(c[ci[i]+1]),endNode(isect[0]);
10212               for(int j=0;j<sz+1;j++)
10213                 {
10214                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10215                     {
10216                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10217                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10218                         { mid[j]=*itc; break; }
10219                     }
10220                   stNode=endNode;
10221                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10222                 }
10223             }
10224         }
10225     }
10226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10227   if(nbOf2DCellsToBeSplit==0)
10228     return ret.retn();
10229   //
10230   int *retPtr(ret->getPointer());
10231   for(int i=0;i<nCell;i++)
10232     if(cells2DToTreat[i])
10233       *retPtr++=i;
10234   //
10235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10236   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10237   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10238   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10239   if(middleNeedsToBeUsed)
10240     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10241   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10242   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10243   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.
10244   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10245   {
10246     bool areNodesMerged; int newNbOfNodes;
10247     if(nbOfNodesCreated!=0)
10248       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10249   }
10250   return ret.retn();
10251 }
10252
10253 /*!
10254  * 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.
10255  * 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).
10256  * 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
10257  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10258  * 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
10259  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10260  *
10261  * 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
10262  * using new instance, idem for coordinates.
10263  *
10264  * 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.
10265  * 
10266  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10267  *
10268  * \throw If \a this is not coherent.
10269  * \throw If \a this has not spaceDim equal to 2.
10270  * \throw If \a this has not meshDim equal to 2.
10271  * 
10272  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10273  */
10274 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10275 {
10276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10277   checkCoherency();
10278   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10280   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10281   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10282   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10283   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10285   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10286   const double *coords(_coords->begin());
10287   int *newciptr(newci->getPointer());
10288   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10289     {
10290       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10291         ret->pushBackSilent(i);
10292       newciptr[1]=newc->getNumberOfTuples();
10293     }
10294   //
10295   if(ret->empty())
10296     return ret.retn();
10297   if(!appendedCoords->empty())
10298     {
10299       appendedCoords->rearrange(2);
10300       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10301       //non const part
10302       setCoords(newCoords);
10303     }
10304   //non const part
10305   setConnectivity(newc,newci,true);
10306   return ret.retn();
10307 }
10308
10309 /*!
10310  * \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.
10311  *                               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.
10312  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10313  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10314  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10315  * \param [out] addCoo - nodes to be append at the end
10316  * \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.
10317  */
10318 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10319                                          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)
10320 {
10321   static const int SPACEDIM=2;
10322   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10323   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10324   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10325   // Build BB tree of all edges in the tool mesh (second mesh)
10326   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10327   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10328   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10329   intersectEdge1.resize(nDescCell1);
10330   colinear2.resize(nDescCell2);
10331   subDiv2.resize(nDescCell2);
10332   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10333
10334   std::vector<int> candidates1(1);
10335   int offset1(m1Desc->getNumberOfNodes());
10336   int offset2(offset1+m2Desc->getNumberOfNodes());
10337   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10338     {
10339       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10340       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10341       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10342         {
10343           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10344           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10345           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10346           candidates1[0]=i;
10347           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10348           // 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
10349           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10350           std::set<INTERP_KERNEL::Node *> nodes;
10351           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10352           std::size_t szz(nodes.size());
10353           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10354           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10355           for(std::size_t iii=0;iii<szz;iii++,itt++)
10356             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10357           // end of protection
10358           // Performs egde cutting:
10359           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10360           delete pol2;
10361           delete pol1;
10362         }
10363       else
10364         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10365         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10366     }
10367 }
10368
10369 /*!
10370  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10371  * It builds the descending connectivity of the two meshes, and then using a binary tree
10372  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10373  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10374  */
10375 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10376                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10377                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10378                                                    std::vector<double>& addCoo,
10379                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10380 {
10381   // Build desc connectivity
10382   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10383   desc2=DataArrayInt::New();
10384   descIndx2=DataArrayInt::New();
10385   revDesc2=DataArrayInt::New();
10386   revDescIndx2=DataArrayInt::New();
10387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10389   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10390   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10391   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10392   std::map<int,int> notUsedMap;
10393   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10394   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10395   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10396 }
10397
10398 /*!
10399  * This method performs the 2nd step of Partition of 2D mesh.
10400  * This method has 4 inputs :
10401  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10402  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10403  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10404  * 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'
10405  * Nodes end up lying consecutively on a cutted edge.
10406  * \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.
10407  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10408  * \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.
10409  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10410  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10411  */
10412 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10413                                            const std::vector<double>& addCoo,
10414                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10415 {
10416   int offset1=m1->getNumberOfNodes();
10417   int ncell=m2->getNumberOfCells();
10418   const int *c=m2->getNodalConnectivity()->getConstPointer();
10419   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10420   const double *coo=m2->getCoords()->getConstPointer();
10421   const double *cooBis=m1->getCoords()->getConstPointer();
10422   int offset2=offset1+m2->getNumberOfNodes();
10423   intersectEdge.resize(ncell);
10424   for(int i=0;i<ncell;i++,cI++)
10425     {
10426       const std::vector<int>& divs=subDiv[i];
10427       int nnode=cI[1]-cI[0]-1;
10428       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10429       std::map<INTERP_KERNEL::Node *, int> mapp22;
10430       for(int j=0;j<nnode;j++)
10431         {
10432           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10433           int nnid=c[(*cI)+j+1];
10434           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10435           mapp22[nn]=nnid+offset1;
10436         }
10437       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10438       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10439         ((*it).second.first)->decrRef();
10440       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10441       std::map<INTERP_KERNEL::Node *,int> mapp3;
10442       for(std::size_t j=0;j<divs.size();j++)
10443         {
10444           int id=divs[j];
10445           INTERP_KERNEL::Node *tmp=0;
10446           if(id<offset1)
10447             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10448           else if(id<offset2)
10449             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10450           else
10451             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10452           addNodes[j]=tmp;
10453           mapp3[tmp]=id;
10454         }
10455       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10456       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10457         (*it)->decrRef();
10458       e->decrRef();
10459     }
10460 }
10461
10462 /*!
10463  * 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).
10464  * 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
10465  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10466  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10467  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10468  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10469  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10470  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10471  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10472  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10473  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10474  * \param [out] cut3DSuf input/output param.
10475  */
10476 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10477                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10478                                                    const int *desc, const int *descIndx, 
10479                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10480 {
10481   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10482   int nbOf3DSurfCell=(int)cut3DSurf.size();
10483   for(int i=0;i<nbOf3DSurfCell;i++)
10484     {
10485       std::vector<int> res;
10486       int offset=descIndx[i];
10487       int nbOfSeg=descIndx[i+1]-offset;
10488       for(int j=0;j<nbOfSeg;j++)
10489         {
10490           int edgeId=desc[offset+j];
10491           int status=cut3DCurve[edgeId];
10492           if(status!=-2)
10493             {
10494               if(status>-1)
10495                 res.push_back(status);
10496               else
10497                 {
10498                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10499                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10500                 }
10501             }
10502         }
10503       switch(res.size())
10504       {
10505         case 2:
10506           {
10507             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10508             break;
10509           }
10510         case 1:
10511         case 0:
10512           {
10513             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10514             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10515             if(res.size()==2)
10516               {
10517                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10518               }
10519             else
10520               {
10521                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10522               }
10523             break;
10524           }
10525         default:
10526           {// case when plane is on a multi colinear edge of a polyhedron
10527             if((int)res.size()==2*nbOfSeg)
10528               {
10529                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10530               }
10531             else
10532               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10533           }
10534       }
10535     }
10536 }
10537
10538 /*!
10539  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10540  * 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).
10541  * 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
10542  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10543  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10544  * \param desc is the descending connectivity 3D->3DSurf
10545  * \param descIndx is the descending connectivity index 3D->3DSurf
10546  */
10547 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10548                                                   const int *desc, const int *descIndx,
10549                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10550 {
10551   checkFullyDefined();
10552   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10553     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10554   const int *nodal3D=_nodal_connec->getConstPointer();
10555   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10556   int nbOfCells=getNumberOfCells();
10557   for(int i=0;i<nbOfCells;i++)
10558     {
10559       std::map<int, std::set<int> > m;
10560       int offset=descIndx[i];
10561       int nbOfFaces=descIndx[i+1]-offset;
10562       int start=-1;
10563       int end=-1;
10564       for(int j=0;j<nbOfFaces;j++)
10565         {
10566           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10567           if(p.first!=-1 && p.second!=-1)
10568             {
10569               if(p.first!=-2)
10570                 {
10571                   start=p.first; end=p.second;
10572                   m[p.first].insert(p.second);
10573                   m[p.second].insert(p.first);
10574                 }
10575               else
10576                 {
10577                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10578                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10579                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10580                   INTERP_KERNEL::NormalizedCellType cmsId;
10581                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10582                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10583                   for(unsigned k=0;k<nbOfNodesSon;k++)
10584                     {
10585                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10586                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10587                     }
10588                 }
10589             }
10590         }
10591       if(m.empty())
10592         continue;
10593       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10594       int prev=end;
10595       while(end!=start)
10596         {
10597           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10598           const std::set<int>& s=(*it).second;
10599           std::set<int> s2; s2.insert(prev);
10600           std::set<int> s3;
10601           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10602           if(s3.size()==1)
10603             {
10604               int val=*s3.begin();
10605               conn.push_back(start);
10606               prev=start;
10607               start=val;
10608             }
10609           else
10610             start=end;
10611         }
10612       conn.push_back(end);
10613       if(conn.size()>3)
10614         {
10615           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10616           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10617           cellIds->pushBackSilent(i);
10618         }
10619     }
10620 }
10621
10622 /*!
10623  * 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
10624  * 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
10625  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10626  * 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
10627  * 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.
10628  * 
10629  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10630  */
10631 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10632 {
10633   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10634   if(sz>=4)
10635     {
10636       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10637       if(cm.getDimension()==2)
10638         {
10639           const int *node=nodalConnBg+1;
10640           int startNode=*node++;
10641           double refX=coords[2*startNode];
10642           for(;node!=nodalConnEnd;node++)
10643             {
10644               if(coords[2*(*node)]<refX)
10645                 {
10646                   startNode=*node;
10647                   refX=coords[2*startNode];
10648                 }
10649             }
10650           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10651           refX=1e300;
10652           double tmp1;
10653           double tmp2[2];
10654           double angle0=-M_PI/2;
10655           //
10656           int nextNode=-1;
10657           int prevNode=-1;
10658           double resRef;
10659           double angleNext=0.;
10660           while(nextNode!=startNode)
10661             {
10662               nextNode=-1;
10663               resRef=1e300;
10664               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10665                 {
10666                   if(*node!=tmpOut.back() && *node!=prevNode)
10667                     {
10668                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10669                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10670                       double res;
10671                       if(angleM<=angle0)
10672                         res=angle0-angleM;
10673                       else
10674                         res=angle0-angleM+2.*M_PI;
10675                       if(res<resRef)
10676                         {
10677                           nextNode=*node;
10678                           resRef=res;
10679                           angleNext=angleM;
10680                         }
10681                     }
10682                 }
10683               if(nextNode!=startNode)
10684                 {
10685                   angle0=angleNext-M_PI;
10686                   if(angle0<-M_PI)
10687                     angle0+=2*M_PI;
10688                   prevNode=tmpOut.back();
10689                   tmpOut.push_back(nextNode);
10690                 }
10691             }
10692           std::vector<int> tmp3(2*(sz-1));
10693           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10694           std::copy(nodalConnBg+1,nodalConnEnd,it);
10695           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10696             {
10697               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10698               return false;
10699             }
10700           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10701             {
10702               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10703               return false;
10704             }
10705           else
10706             {
10707               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10708               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10709               return true;
10710             }
10711         }
10712       else
10713         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10714     }
10715   else
10716     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10717 }
10718
10719 /*!
10720  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10721  * 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.
10722  * 
10723  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10724  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10725  * \param [in,out] arr array in which the remove operation will be done.
10726  * \param [in,out] arrIndx array in the remove operation will modify
10727  * \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])
10728  * \return true if \b arr and \b arrIndx have been modified, false if not.
10729  */
10730 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10731 {
10732   if(!arrIndx || !arr)
10733     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10734   if(offsetForRemoval<0)
10735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10736   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10737   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10738   int *arrIPtr=arrIndx->getPointer();
10739   *arrIPtr++=0;
10740   int previousArrI=0;
10741   const int *arrPtr=arr->getConstPointer();
10742   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10743   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10744     {
10745       if(*arrIPtr-previousArrI>offsetForRemoval)
10746         {
10747           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10748             {
10749               if(s.find(*work)==s.end())
10750                 arrOut.push_back(*work);
10751             }
10752         }
10753       previousArrI=*arrIPtr;
10754       *arrIPtr=(int)arrOut.size();
10755     }
10756   if(arr->getNumberOfTuples()==(int)arrOut.size())
10757     return false;
10758   arr->alloc((int)arrOut.size(),1);
10759   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10760   return true;
10761 }
10762
10763 /*!
10764  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10765  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10766  * The selection of extraction is done standardly in new2old format.
10767  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10768  *
10769  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10770  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10771  * \param [in] arrIn arr origin array from which the extraction will be done.
10772  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10773  * \param [out] arrOut the resulting array
10774  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10775  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10776  */
10777 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10778                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10779 {
10780   if(!arrIn || !arrIndxIn)
10781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10782   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10783   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10785   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10786   const int *arrInPtr=arrIn->getConstPointer();
10787   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10788   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10789   if(nbOfGrps<0)
10790     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10791   int maxSizeOfArr=arrIn->getNumberOfTuples();
10792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10794   arrIo->alloc((int)(sz+1),1);
10795   const int *idsIt=idsOfSelectBg;
10796   int *work=arrIo->getPointer();
10797   *work++=0;
10798   int lgth=0;
10799   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10800     {
10801       if(*idsIt>=0 && *idsIt<nbOfGrps)
10802         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10803       else
10804         {
10805           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10806           throw INTERP_KERNEL::Exception(oss.str().c_str());
10807         }
10808       if(lgth>=work[-1])
10809         *work=lgth;
10810       else
10811         {
10812           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10813           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10814           throw INTERP_KERNEL::Exception(oss.str().c_str());
10815         }
10816     }
10817   arro->alloc(lgth,1);
10818   work=arro->getPointer();
10819   idsIt=idsOfSelectBg;
10820   for(std::size_t i=0;i<sz;i++,idsIt++)
10821     {
10822       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10823         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10824       else
10825         {
10826           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10827           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10828           throw INTERP_KERNEL::Exception(oss.str().c_str());
10829         }
10830     }
10831   arrOut=arro.retn();
10832   arrIndexOut=arrIo.retn();
10833 }
10834
10835 /*!
10836  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10837  * 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 ).
10838  * The selection of extraction is done standardly in new2old format.
10839  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10840  *
10841  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10842  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10843  * \param [in] arrIn arr origin array from which the extraction will be done.
10844  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10845  * \param [out] arrOut the resulting array
10846  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10847  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10848  */
10849 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10850                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10851 {
10852   if(!arrIn || !arrIndxIn)
10853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10854   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10855   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10857   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10858   const int *arrInPtr=arrIn->getConstPointer();
10859   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10860   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10861   if(nbOfGrps<0)
10862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10863   int maxSizeOfArr=arrIn->getNumberOfTuples();
10864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10866   arrIo->alloc((int)(sz+1),1);
10867   int idsIt=idsOfSelectStart;
10868   int *work=arrIo->getPointer();
10869   *work++=0;
10870   int lgth=0;
10871   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10872     {
10873       if(idsIt>=0 && idsIt<nbOfGrps)
10874         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10875       else
10876         {
10877           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10878           throw INTERP_KERNEL::Exception(oss.str().c_str());
10879         }
10880       if(lgth>=work[-1])
10881         *work=lgth;
10882       else
10883         {
10884           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10885           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10886           throw INTERP_KERNEL::Exception(oss.str().c_str());
10887         }
10888     }
10889   arro->alloc(lgth,1);
10890   work=arro->getPointer();
10891   idsIt=idsOfSelectStart;
10892   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10893     {
10894       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10895         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10896       else
10897         {
10898           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10899           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10900           throw INTERP_KERNEL::Exception(oss.str().c_str());
10901         }
10902     }
10903   arrOut=arro.retn();
10904   arrIndexOut=arrIo.retn();
10905 }
10906
10907 /*!
10908  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10909  * 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
10910  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10911  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10912  *
10913  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10914  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10915  * \param [in] arrIn arr origin array from which the extraction will be done.
10916  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10917  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10918  * \param [in] srcArrIndex index array of \b srcArr
10919  * \param [out] arrOut the resulting array
10920  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10921  * 
10922  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10923  */
10924 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10925                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10926                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10927 {
10928   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10930   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10931   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10932   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10933   std::vector<bool> v(nbOfTuples,true);
10934   int offset=0;
10935   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10936   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10937   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10938     {
10939       if(*it>=0 && *it<nbOfTuples)
10940         {
10941           v[*it]=false;
10942           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10943         }
10944       else
10945         {
10946           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10947           throw INTERP_KERNEL::Exception(oss.str().c_str());
10948         }
10949     }
10950   srcArrIndexPtr=srcArrIndex->getConstPointer();
10951   arrIo->alloc(nbOfTuples+1,1);
10952   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10953   const int *arrInPtr=arrIn->getConstPointer();
10954   const int *srcArrPtr=srcArr->getConstPointer();
10955   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10956   int *arroPtr=arro->getPointer();
10957   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10958     {
10959       if(v[ii])
10960         {
10961           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10962           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10963         }
10964       else
10965         {
10966           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10967           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10968           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10969         }
10970     }
10971   arrOut=arro.retn();
10972   arrIndexOut=arrIo.retn();
10973 }
10974
10975 /*!
10976  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10977  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10978  *
10979  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10980  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10981  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10982  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10983  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10984  * \param [in] srcArrIndex index array of \b srcArr
10985  * 
10986  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10987  */
10988 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10989                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10990 {
10991   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10993   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10994   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10995   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10996   int *arrInOutPtr=arrInOut->getPointer();
10997   const int *srcArrPtr=srcArr->getConstPointer();
10998   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10999     {
11000       if(*it>=0 && *it<nbOfTuples)
11001         {
11002           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11003             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11004           else
11005             {
11006               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] !";
11007               throw INTERP_KERNEL::Exception(oss.str().c_str());
11008             }
11009         }
11010       else
11011         {
11012           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11013           throw INTERP_KERNEL::Exception(oss.str().c_str());
11014         }
11015     }
11016 }
11017
11018 /*!
11019  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11020  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11021  * 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]].
11022  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11023  * A negative value in \b arrIn means that it is ignored.
11024  * 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.
11025  * 
11026  * \param [in] arrIn arr origin array from which the extraction will be done.
11027  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11028  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11029  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11030  */
11031 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11032 {
11033   int seed=0,nbOfDepthPeelingPerformed=0;
11034   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11035 }
11036
11037 /*!
11038  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11039  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11040  * 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]].
11041  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11042  * A negative value in \b arrIn means that it is ignored.
11043  * 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.
11044  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11045  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11046  * \param [in] arrIn arr origin array from which the extraction will be done.
11047  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11048  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11049  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11050  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11051  * \sa MEDCouplingUMesh::partitionBySpreadZone
11052  */
11053 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11054 {
11055   nbOfDepthPeelingPerformed=0;
11056   if(!arrIndxIn)
11057     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11058   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11059   if(nbOfTuples<=0)
11060     {
11061       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11062       return ret;
11063     }
11064   //
11065   std::vector<bool> fetched(nbOfTuples,false);
11066   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11067 }
11068
11069 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11070 {
11071   nbOfDepthPeelingPerformed=0;
11072   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11074   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11075   std::vector<bool> fetched2(nbOfTuples,false);
11076   int i=0;
11077   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11078     {
11079       if(*seedElt>=0 && *seedElt<nbOfTuples)
11080         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11081       else
11082         { 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()); }
11083     }
11084   const int *arrInPtr=arrIn->getConstPointer();
11085   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11086   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11087   std::vector<int> idsToFetch1(seedBg,seedEnd);
11088   std::vector<int> idsToFetch2;
11089   std::vector<int> *idsToFetch=&idsToFetch1;
11090   std::vector<int> *idsToFetchOther=&idsToFetch2;
11091   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11092     {
11093       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11094         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11095           if(!fetched[*it2])
11096             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11097       std::swap(idsToFetch,idsToFetchOther);
11098       idsToFetchOther->clear();
11099       nbOfDepthPeelingPerformed++;
11100     }
11101   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11102   i=0;
11103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11104   int *retPtr=ret->getPointer();
11105   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11106     if(*it)
11107       *retPtr++=i;
11108   return ret.retn();
11109 }
11110
11111 /*!
11112  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11113  * 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
11114  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11115  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11116  *
11117  * \param [in] start begin of set of ids of the input extraction (included)
11118  * \param [in] end end of set of ids of the input extraction (excluded)
11119  * \param [in] step step of the set of ids in range mode.
11120  * \param [in] arrIn arr origin array from which the extraction will be done.
11121  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11122  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11123  * \param [in] srcArrIndex index array of \b srcArr
11124  * \param [out] arrOut the resulting array
11125  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11126  * 
11127  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11128  */
11129 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11130                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11131                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11132 {
11133   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11137   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11138   int offset=0;
11139   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11140   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11141   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11142   int it=start;
11143   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11144     {
11145       if(it>=0 && it<nbOfTuples)
11146         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11147       else
11148         {
11149           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11150           throw INTERP_KERNEL::Exception(oss.str().c_str());
11151         }
11152     }
11153   srcArrIndexPtr=srcArrIndex->getConstPointer();
11154   arrIo->alloc(nbOfTuples+1,1);
11155   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11156   const int *arrInPtr=arrIn->getConstPointer();
11157   const int *srcArrPtr=srcArr->getConstPointer();
11158   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11159   int *arroPtr=arro->getPointer();
11160   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11161     {
11162       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11163       if(pos<0)
11164         {
11165           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11166           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11167         }
11168       else
11169         {
11170           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11171           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11172         }
11173     }
11174   arrOut=arro.retn();
11175   arrIndexOut=arrIo.retn();
11176 }
11177
11178 /*!
11179  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11180  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11181  *
11182  * \param [in] start begin of set of ids of the input extraction (included)
11183  * \param [in] end end of set of ids of the input extraction (excluded)
11184  * \param [in] step step of the set of ids in range mode.
11185  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11186  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11187  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11188  * \param [in] srcArrIndex index array of \b srcArr
11189  * 
11190  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11191  */
11192 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11193                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11194 {
11195   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11196     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11197   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11198   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11199   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11200   int *arrInOutPtr=arrInOut->getPointer();
11201   const int *srcArrPtr=srcArr->getConstPointer();
11202   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11203   int it=start;
11204   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11205     {
11206       if(it>=0 && it<nbOfTuples)
11207         {
11208           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11209             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11210           else
11211             {
11212               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11213               throw INTERP_KERNEL::Exception(oss.str().c_str());
11214             }
11215         }
11216       else
11217         {
11218           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11219           throw INTERP_KERNEL::Exception(oss.str().c_str());
11220         }
11221     }
11222 }
11223
11224 /*!
11225  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11226  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11227  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11228  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11229  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11230  * 
11231  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11232  */
11233 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11234 {
11235   checkFullyDefined();
11236   int mdim=getMeshDimension();
11237   int spaceDim=getSpaceDimension();
11238   if(mdim!=spaceDim)
11239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11240   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11241   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11242   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11243   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11244   ret->setCoords(getCoords());
11245   ret->allocateCells((int)partition.size());
11246   //
11247   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11248     {
11249       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11250       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11251       switch(mdim)
11252       {
11253         case 2:
11254           cell=tmp->buildUnionOf2DMesh();
11255           break;
11256         case 3:
11257           cell=tmp->buildUnionOf3DMesh();
11258           break;
11259         default:
11260           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11261       }
11262
11263       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11264     }
11265   //
11266   ret->finishInsertingCells();
11267   return ret.retn();
11268 }
11269
11270 /*!
11271  * This method partitions \b this into contiguous zone.
11272  * This method only needs a well defined connectivity. Coordinates are not considered here.
11273  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11274  */
11275 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11276 {
11277   int nbOfCellsCur=getNumberOfCells();
11278   std::vector<DataArrayInt *> ret;
11279   if(nbOfCellsCur<=0)
11280     return ret;
11281   DataArrayInt *neigh=0,*neighI=0;
11282   computeNeighborsOfCells(neigh,neighI);
11283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11284   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11285   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11286   int seed=0;
11287   while(seed<nbOfCellsCur)
11288     {
11289       int nbOfPeelPerformed=0;
11290       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11291       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11292     }
11293   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11294     ret.push_back((*it).retn());
11295   return ret;
11296 }
11297
11298 /*!
11299  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11300  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11301  *
11302  * \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.
11303  * \return a newly allocated DataArrayInt to be managed by the caller.
11304  * \throw In case of \a code has not the right format (typically of size 3*n)
11305  */
11306 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11307 {
11308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11309   std::size_t nb=code.size()/3;
11310   if(code.size()%3!=0)
11311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11312   ret->alloc((int)nb,2);
11313   int *retPtr=ret->getPointer();
11314   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11315     {
11316       retPtr[0]=code[3*i+2];
11317       retPtr[1]=code[3*i+2]+code[3*i+1];
11318     }
11319   return ret.retn();
11320 }
11321
11322 /*!
11323  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11324  * All cells in \a this are expected to be linear 3D cells.
11325  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11326  * It leads to an increase to number of cells.
11327  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11328  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11329  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11330  *
11331  * \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.
11332  *                      For all other cells, the splitting policy will be ignored.
11333  * \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. 
11334  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11335  *          an id of old cell producing it. The caller is to delete this array using
11336  *         decrRef() as it is no more needed.
11337  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11338  *
11339  * \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
11340  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11341  * 
11342  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11343  * \throw If \a this is not fully constituted with linear 3D cells.
11344  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11345  */
11346 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11347 {
11348   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11349   checkConnectivityFullyDefined();
11350   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11352   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11353   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11355   int *retPt(ret->getPointer());
11356   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11357   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11358   const int *oldc(_nodal_connec->begin());
11359   const int *oldci(_nodal_connec_index->begin());
11360   const double *coords(_coords->begin());
11361   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11362     {
11363       std::vector<int> a; std::vector<double> b;
11364       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11365       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11366       const int *aa(&a[0]);
11367       if(!b.empty())
11368         {
11369           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11370             if(*it<0)
11371               *it=(-(*(it))-1+nbNodes);
11372           addPts->insertAtTheEnd(b.begin(),b.end());
11373           nbNodes+=(int)b.size()/3;
11374         }
11375       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11376         newConn->insertAtTheEnd(aa,aa+4);
11377     }
11378   if(!addPts->empty())
11379     {
11380       addPts->rearrange(3);
11381       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11382       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11383       ret0->setCoords(addPts);
11384     }
11385   else
11386     {
11387       nbOfAdditionalPoints=0;
11388       ret0->setCoords(getCoords());
11389     }
11390   ret0->setNodalConnectivity(newConn);
11391   //
11392   ret->computeOffsets2();
11393   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11394   return ret0.retn();
11395 }
11396
11397 /*!
11398  * 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). 
11399  *
11400  * \sa MEDCouplingUMesh::split2DCells
11401  */
11402 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11403 {
11404   checkConnectivityFullyDefined();
11405   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11407   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11408   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11409   int prevPosOfCi(ciPtr[0]);
11410   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11411     {
11412       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11413       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11414       for(int j=0;j<sz;j++)
11415         {
11416           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11417           for(int k=0;k<sz2;k++)
11418             *cPtr++=subPtr[offset2+k];
11419           if(j!=sz-1)
11420             *cPtr++=oldConn[prevPosOfCi+j+2];
11421           deltaSz+=sz2;
11422         }
11423       prevPosOfCi=ciPtr[1];
11424       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11425     }
11426   if(c->end()!=cPtr)
11427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11428   _nodal_connec->decrRef();
11429   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11430 }
11431
11432 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11433 {
11434   if(id!=-1)
11435     return id;
11436   else
11437     {
11438       int ret(nodesCnter++);
11439       double newPt[2];
11440       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11441       addCoo.insertAtTheEnd(newPt,newPt+2);
11442       return ret;
11443     }
11444 }
11445
11446 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11447 {
11448   if(id!=-1)
11449     return id;
11450   else
11451     {
11452       int ret(nodesCnter++);
11453       double newPt[2];
11454       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11455       addCoo.insertAtTheEnd(newPt,newPt+2);
11456       return ret;
11457     }
11458 }
11459
11460
11461 /// @cond INTERNAL
11462
11463 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)
11464 {
11465   int tmp[3];
11466   int trueStart(start>=0?start:nbOfEdges+start);
11467   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11468   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11469   if(linOrArc)
11470     {
11471       if(stp-start>1)
11472         {
11473           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11474           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11475           middles.push_back(tmp3+offset);
11476         }
11477       else
11478         middles.push_back(connBg[trueStart+nbOfEdges]);
11479     }
11480 }
11481
11482 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)
11483 {
11484   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11485   newConnOfCell->pushBackSilent(tmpEnd);
11486   if(linOrArc)
11487     {
11488       if(stp-start>1)
11489         {
11490           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11491           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11492           middles.push_back(tmp3+offset);
11493         }
11494       else
11495         middles.push_back(connBg[start+nbOfEdges]);
11496     }
11497 }
11498
11499 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)
11500 {
11501   // only the quadratic point to deal with:
11502   if(linOrArc)
11503     {
11504       if(stp-start>1)
11505         {
11506           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11507           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11508           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11509           middles.push_back(tmp3+offset);
11510         }
11511       else
11512         middles.push_back(connBg[start+nbOfEdges]);
11513     }
11514 }
11515
11516 /// @cond INTERNAL
11517
11518 /*!
11519  * 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 ) .
11520  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11521  */
11522 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11523 {
11524   std::size_t sz(std::distance(connBg,connEnd));
11525   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11526     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11527   sz--;
11528   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11529   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11530   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11531   unsigned nbOfHit(0); // number of fusions operated
11532   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11533   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
11534   INTERP_KERNEL::NormalizedCellType typeOfSon;
11535   std::vector<int> middles;
11536   bool ret(false);
11537   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11538     {
11539       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11540       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11541       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11542       posEndElt = posBaseElt+1;
11543
11544       // Look backward first: are the final edges of the cells colinear with the first ones?
11545       // This initializes posBaseElt.
11546       if(nbOfTurn==0)
11547         {
11548           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11549             {
11550               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11551               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11552               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11553               bool isColinear=eint->areColinears();
11554               if(isColinear)
11555                 {
11556                   nbOfHit++;
11557                   posBaseElt--;
11558                   ret=true;
11559                 }
11560               delete eint;
11561               eCand->decrRef();
11562               if(!isColinear)
11563                 break;
11564             }
11565         }
11566       // Now move forward:
11567       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11568       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11569         {
11570           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11571           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11572           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11573           bool isColinear(eint->areColinears());
11574           if(isColinear)
11575             {
11576               nbOfHit++;
11577               posEndElt++;
11578               ret=true;
11579             }
11580           delete eint;
11581           eCand->decrRef();
11582           if(!isColinear)
11583               break;
11584         }
11585       //push [posBaseElt,posEndElt) in newConnOfCell using e
11586       // 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!
11587       if(nbOfTurn==0)
11588         // at the begining of the connectivity (insert type)
11589         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11590       else if((nbOfHit+nbOfTurn) != (nbs-1))
11591         // in the middle
11592         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11593       if ((nbOfHit+nbOfTurn) == (nbs-1))
11594         // at the end (only quad points to deal with)
11595         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11596       posBaseElt=posEndElt;
11597       e->decrRef();
11598     }
11599   if(!middles.empty())
11600     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11601   return ret;
11602 }
11603
11604 /*!
11605  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11606  *
11607  * \return  int - the number of new nodes created.
11608  * \sa MEDCouplingUMesh::split2DCells
11609  */
11610 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11611 {
11612   checkCoherency();
11613   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11614   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11615   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11616   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11617   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11618   const double *oldCoordsPtr(getCoords()->begin());
11619   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11620   int prevPosOfCi(ciPtr[0]);
11621   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11622     {
11623       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11624       for(int j=0;j<sz;j++)
11625         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11626       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11627       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11628         {
11629           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11630           if(sz2==0)
11631             {
11632               if(j<sz-1)
11633                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11634               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11635               continue;
11636             }
11637           std::vector<INTERP_KERNEL::Node *> ns(3);
11638           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11639           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11640           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11641           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11642           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11643             {
11644               cPtr[1]=subPtr[offset2+k];
11645               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11646             }
11647           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11648           if(j!=sz-1)
11649             { cPtr[1]=tmpEnd; }
11650           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11651         }
11652       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11653       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11654     }
11655   if(c->end()!=cPtr)
11656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11657   _nodal_connec->decrRef();
11658   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11659   addCoo->rearrange(2);
11660   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11661   setCoords(coo);
11662   return addCoo->getNumberOfTuples();
11663 }
11664
11665 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11666 {
11667   if(nodalConnec && nodalConnecIndex)
11668     {
11669       types.clear();
11670       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11671       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11672       if(nbOfElem>0)
11673         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11674           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11675     }
11676 }
11677
11678 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11679     _own_cell(true),_cell_id(-1),_nb_cell(0)
11680 {
11681   if(mesh)
11682     {
11683       mesh->incrRef();
11684       _nb_cell=mesh->getNumberOfCells();
11685     }
11686 }
11687
11688 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11689 {
11690   if(_mesh)
11691     _mesh->decrRef();
11692   if(_own_cell)
11693     delete _cell;
11694 }
11695
11696 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11697     _own_cell(false),_cell_id(bg-1),
11698     _nb_cell(end)
11699 {
11700   if(mesh)
11701     mesh->incrRef();
11702 }
11703
11704 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11705 {
11706   _cell_id++;
11707   if(_cell_id<_nb_cell)
11708     {
11709       _cell->next();
11710       return _cell;
11711     }
11712   else
11713     return 0;
11714 }
11715
11716 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11717 {
11718   if(_mesh)
11719     _mesh->incrRef();
11720 }
11721
11722 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11723 {
11724   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11725 }
11726
11727 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11728 {
11729   if(_mesh)
11730     _mesh->decrRef();
11731 }
11732
11733 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11734     _itc(itc),
11735     _bg(bg),_end(end)
11736 {
11737   if(_mesh)
11738     _mesh->incrRef();
11739 }
11740
11741 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11742 {
11743   if(_mesh)
11744     _mesh->decrRef();
11745 }
11746
11747 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11748 {
11749   return _type;
11750 }
11751
11752 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11753 {
11754   return _end-_bg;
11755 }
11756
11757 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11758 {
11759   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11760 }
11761
11762 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11763 {
11764   if(mesh)
11765     {
11766       mesh->incrRef();
11767       _nb_cell=mesh->getNumberOfCells();
11768     }
11769 }
11770
11771 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11772 {
11773   if(_mesh)
11774     _mesh->decrRef();
11775   delete _cell;
11776 }
11777
11778 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11779 {
11780   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11781   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11782   if(_cell_id<_nb_cell)
11783     {
11784       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11785       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11786       int startId=_cell_id;
11787       _cell_id+=nbOfElems;
11788       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11789     }
11790   else
11791     return 0;
11792 }
11793
11794 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11795 {
11796   if(mesh)
11797     {
11798       _conn=mesh->getNodalConnectivity()->getPointer();
11799       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11800     }
11801 }
11802
11803 void MEDCouplingUMeshCell::next()
11804 {
11805   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11806     {
11807       _conn+=_conn_lgth;
11808       _conn_indx++;
11809     }
11810   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11811 }
11812
11813 std::string MEDCouplingUMeshCell::repr() const
11814 {
11815   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11816     {
11817       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11818       oss << " : ";
11819       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11820       return oss.str();
11821     }
11822   else
11823     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11824 }
11825
11826 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11827 {
11828   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11829     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11830   else
11831     return INTERP_KERNEL::NORM_ERROR;
11832 }
11833
11834 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11835 {
11836   lgth=_conn_lgth;
11837   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11838     return _conn;
11839   else
11840     return 0;
11841 }