]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDCoupling/MEDCouplingUMesh.cxx
Salome HOME
factorizations continue
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  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.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
93 {
94   if(!other)
95     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
96   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
97   if(!otherC)
98     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
99   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
100   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
101 }
102
103 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
104 {
105   std::size_t ret=0;
106   if(_nodal_connec)
107     ret+=_nodal_connec->getHeapMemorySize();
108   if(_nodal_connec_index)
109     ret+=_nodal_connec_index->getHeapMemorySize();
110   return MEDCouplingPointSet::getHeapMemorySize()+ret;
111 }
112
113 void MEDCouplingUMesh::updateTime() const
114 {
115   MEDCouplingPointSet::updateTime();
116   if(_nodal_connec)
117     {
118       updateTimeWith(*_nodal_connec);
119     }
120   if(_nodal_connec_index)
121     {
122       updateTimeWith(*_nodal_connec_index);
123     }
124 }
125
126 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
127 {
128 }
129
130 /*!
131  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
132  * then \a this mesh is most probably is writable, exchangeable and available for most
133  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
134  * this method to check that all is in order with \a this mesh.
135  *  \throw If the mesh dimension is not set.
136  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
137  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
138  *  \throw If the connectivity data array has more than one component.
139  *  \throw If the connectivity data array has a named component.
140  *  \throw If the connectivity index data array has more than one component.
141  *  \throw If the connectivity index data array has a named component.
142  */
143 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
144 {
145   if(_mesh_dim<-1)
146    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
147   if(_mesh_dim!=-1)
148     MEDCouplingPointSet::checkCoherency();
149   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
150     {
151       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
152         {
153           std::ostringstream message;
154           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
155           throw INTERP_KERNEL::Exception(message.str().c_str());
156         }
157     }
158   if(_nodal_connec)
159     {
160       if(_nodal_connec->getNumberOfComponents()!=1)
161         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
162       if(_nodal_connec->getInfoOnComponent(0)!="")
163         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
164     }
165   else
166     if(_mesh_dim!=-1)
167       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
168   if(_nodal_connec_index)
169     {
170       if(_nodal_connec_index->getNumberOfComponents()!=1)
171         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
172       if(_nodal_connec_index->getInfoOnComponent(0)!="")
173         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
174     }
175   else
176     if(_mesh_dim!=-1)
177       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
178 }
179
180 /*!
181  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
182  * then \a this mesh is most probably is writable, exchangeable and available for all
183  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
184  * method thoroughly checks the nodal connectivity.
185  *  \param [in] eps - a not used parameter.
186  *  \throw If the mesh dimension is not set.
187  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
188  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
189  *  \throw If the connectivity data array has more than one component.
190  *  \throw If the connectivity data array has a named component.
191  *  \throw If the connectivity index data array has more than one component.
192  *  \throw If the connectivity index data array has a named component.
193  *  \throw If number of nodes defining an element does not correspond to the type of element.
194  *  \throw If the nodal connectivity includes an invalid node id.
195  */
196 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
197 {
198   checkCoherency();
199   if(_mesh_dim==-1)
200     return ;
201   int meshDim=getMeshDimension();
202   int nbOfNodes=getNumberOfNodes();
203   int nbOfCells=getNumberOfCells();
204   const int *ptr=_nodal_connec->getConstPointer();
205   const int *ptrI=_nodal_connec_index->getConstPointer();
206   for(int i=0;i<nbOfCells;i++)
207     {
208       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
209       if((int)cm.getDimension()!=meshDim)
210         {
211           std::ostringstream oss;
212           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
213           throw INTERP_KERNEL::Exception(oss.str().c_str());
214         }
215       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
216       if(!cm.isDynamic())
217         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
218           {
219             std::ostringstream oss;
220             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
221             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
222             throw INTERP_KERNEL::Exception(oss.str().c_str());
223           }
224       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
225         {
226           int nodeId=*w;
227           if(nodeId>=0)
228             {
229               if(nodeId>=nbOfNodes)
230                 {
231                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
232                   throw INTERP_KERNEL::Exception(oss.str().c_str());
233                 }
234             }
235           else if(nodeId<-1)
236             {
237               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
238               throw INTERP_KERNEL::Exception(oss.str().c_str());
239             }
240           else
241             {
242               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
243                 {
244                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
245                   throw INTERP_KERNEL::Exception(oss.str().c_str());
246                 }
247             }
248         }
249     }
250 }
251
252
253 /*!
254  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
255  * then \a this mesh is most probably is writable, exchangeable and available for all
256  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
257  *  \param [in] eps - a not used parameter.
258  *  \throw If the mesh dimension is not set.
259  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
260  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
261  *  \throw If the connectivity data array has more than one component.
262  *  \throw If the connectivity data array has a named component.
263  *  \throw If the connectivity index data array has more than one component.
264  *  \throw If the connectivity index data array has a named component.
265  *  \throw If number of nodes defining an element does not correspond to the type of element.
266  *  \throw If the nodal connectivity includes an invalid node id.
267  */
268 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
269 {
270   checkCoherency1(eps);
271 }
272
273 /*!
274  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
275  * elements contained in the mesh. For more info on the mesh dimension see
276  * \ref MEDCouplingUMeshPage.
277  *  \param [in] meshDim - a new mesh dimension.
278  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
279  */
280 void MEDCouplingUMesh::setMeshDimension(int meshDim)
281 {
282   if(meshDim<-1 || meshDim>3)
283     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
284   _mesh_dim=meshDim;
285   declareAsNew();
286 }
287
288 /*!
289  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
290  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
291  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
292  *
293  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
294  *
295  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
296  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
297  */
298 void MEDCouplingUMesh::allocateCells(int nbOfCells)
299 {
300   if(nbOfCells<0)
301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
302   if(_nodal_connec_index)
303     {
304       _nodal_connec_index->decrRef();
305     }
306   if(_nodal_connec)
307     {
308       _nodal_connec->decrRef();
309     }
310   _nodal_connec_index=DataArrayInt::New();
311   _nodal_connec_index->reserve(nbOfCells+1);
312   _nodal_connec_index->pushBackSilent(0);
313   _nodal_connec=DataArrayInt::New();
314   _nodal_connec->reserve(2*nbOfCells);
315   _types.clear();
316   declareAsNew();
317 }
318
319 /*!
320  * Appends a cell to the connectivity array. For deeper understanding what is
321  * happening see \ref MEDCouplingUMeshNodalConnectivity.
322  *  \param [in] type - type of cell to add.
323  *  \param [in] size - number of nodes constituting this cell.
324  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
325  * 
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  */
329 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
330 {
331   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
332   if(_nodal_connec_index==0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
334   if((int)cm.getDimension()==_mesh_dim)
335     {
336       if(!cm.isDynamic())
337         if(size!=(int)cm.getNumberOfNodes())
338           {
339             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
340             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
341             throw INTERP_KERNEL::Exception(oss.str().c_str());
342           }
343       int idx=_nodal_connec_index->back();
344       int val=idx+size+1;
345       _nodal_connec_index->pushBackSilent(val);
346       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
347       _types.insert(type);
348     }
349   else
350     {
351       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
352       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
353       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
354       throw INTERP_KERNEL::Exception(oss.str().c_str());
355     }
356 }
357
358 /*!
359  * Compacts data arrays to release unused memory. This method is to be called after
360  * finishing cell insertion using \a this->insertNextCell().
361  * 
362  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
364  */
365 void MEDCouplingUMesh::finishInsertingCells()
366 {
367   _nodal_connec->pack();
368   _nodal_connec_index->pack();
369   _nodal_connec->declareAsNew();
370   _nodal_connec_index->declareAsNew();
371   updateTime();
372 }
373
374 /*!
375  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
376  * Useful for python users.
377  */
378 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
379 {
380   return new MEDCouplingUMeshCellIterator(this);
381 }
382
383 /*!
384  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
385  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
386  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
387  * Useful for python users.
388  */
389 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
390 {
391   if(!checkConsecutiveCellTypes())
392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
393   return new MEDCouplingUMeshCellByTypeEntry(this);
394 }
395
396 /*!
397  * Returns a set of all cell types available in \a this mesh.
398  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
399  * \warning this method does not throw any exception even if \a this is not defined.
400  */
401 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
402 {
403   return _types;
404 }
405
406 /*!
407  * This method is a method that compares \a this and \a other.
408  * This method compares \b all attributes, even names and component names.
409  */
410 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
411 {
412   if(!other)
413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
414   std::ostringstream oss; oss.precision(15);
415   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
416   if(!otherC)
417     {
418       reason="mesh given in input is not castable in MEDCouplingUMesh !";
419       return false;
420     }
421   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
422     return false;
423   if(_mesh_dim!=otherC->_mesh_dim)
424     {
425       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
426       reason=oss.str();
427       return false;
428     }
429   if(_types!=otherC->_types)
430     {
431       oss << "umesh geometric type mismatch :\nThis geometric types are :";
432       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
433         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
434       oss << "\nOther geometric types are :";
435       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
436         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
437       reason=oss.str();
438       return false;
439     }
440   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
441     if(_nodal_connec==0 || otherC->_nodal_connec==0)
442       {
443         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
444         return false;
445       }
446   if(_nodal_connec!=otherC->_nodal_connec)
447     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
448       {
449         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
450         return false;
451       }
452   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
453     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
454       {
455         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
456         return false;
457       }
458   if(_nodal_connec_index!=otherC->_nodal_connec_index)
459     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
460       {
461         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
462         return false;
463       }
464   return true;
465 }
466
467 /*!
468  * Checks if data arrays of this mesh (node coordinates, nodal
469  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
470  * not considered.
471  *  \param [in] other - the mesh to compare with.
472  *  \param [in] prec - precision value used to compare node coordinates.
473  *  \return bool - \a true if the two meshes are same.
474  */
475 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
476 {
477   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
478   if(!otherC)
479     return false;
480   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
481     return false;
482   if(_mesh_dim!=otherC->_mesh_dim)
483     return false;
484   if(_types!=otherC->_types)
485     return false;
486   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
487     if(_nodal_connec==0 || otherC->_nodal_connec==0)
488       return false;
489   if(_nodal_connec!=otherC->_nodal_connec)
490     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
491       return false;
492   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
493     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
494       return false;
495   if(_nodal_connec_index!=otherC->_nodal_connec_index)
496     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
497       return false;
498   return true;
499 }
500
501 /*!
502  * Checks if \a this and \a other meshes are geometrically equivalent with high
503  * probability, else an exception is thrown. The meshes are considered equivalent if
504  * (1) meshes contain the same number of nodes and the same number of elements of the
505  * same types (2) three cells of the two meshes (first, last and middle) are based
506  * on coincident nodes (with a specified precision).
507  *  \param [in] other - the mesh to compare with.
508  *  \param [in] prec - the precision used to compare nodes of the two meshes.
509  *  \throw If the two meshes do not match.
510  */
511 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
512 {
513  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
514  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
515   if(!otherC)
516     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
517 }
518
519 /*!
520  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
521  * cells each node belongs to.
522  * \warning For speed reasons, this method does not check if node ids in the nodal
523  *          connectivity correspond to the size of node coordinates array.
524  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
525  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
526  *        dividing cell ids in \a revNodal into groups each referring to one
527  *        node. Its every element (except the last one) is an index pointing to the
528  *         first id of a group of cells. For example cells sharing the node #1 are 
529  *        described by following range of indices: 
530  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
531  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
532  *        Number of cells sharing the *i*-th node is
533  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
534  * \throw If the coordinates array is not set.
535  * \throw If the nodal connectivity of cells is not defined.
536  * 
537  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
538  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
539  */
540 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
541 {
542   checkFullyDefined();
543   int nbOfNodes=getNumberOfNodes();
544   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
545   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
546   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
547   const int *conn=_nodal_connec->getConstPointer();
548   const int *connIndex=_nodal_connec_index->getConstPointer();
549   int nbOfCells=getNumberOfCells();
550   int nbOfEltsInRevNodal=0;
551   for(int eltId=0;eltId<nbOfCells;eltId++)
552     {
553       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
554       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
555       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
556         if(*iter>=0)//for polyhedrons
557           {
558             nbOfEltsInRevNodal++;
559             revNodalIndxPtr[(*iter)+1]++;
560           }
561     }
562   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
563   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
564   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
565   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
566   for(int eltId=0;eltId<nbOfCells;eltId++)
567     {
568       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571         if(*iter>=0)//for polyhedrons
572           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
573     }
574 }
575
576 /// @cond INTERNAL
577
578 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
579 {
580   return id;
581 }
582
583 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
584 {
585   if(!compute)
586     return id+1;
587   else
588     {
589       if(cm.getOrientationStatus(nb,conn1,conn2))
590         return id+1;
591       else
592         return -(id+1);
593     }
594 }
595
596 class MinusOneSonsGenerator
597 {
598 public:
599   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
600   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
601   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
602   static const int DELTA=1;
603 private:
604   const INTERP_KERNEL::CellModel& _cm;
605 };
606
607 class MinusOneSonsGeneratorBiQuadratic
608 {
609 public:
610   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
611   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
612   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
613   static const int DELTA=1;
614 private:
615   const INTERP_KERNEL::CellModel& _cm;
616 };
617
618 class MinusTwoSonsGenerator
619 {
620 public:
621   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
623   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624   static const int DELTA=2;
625 private:
626   const INTERP_KERNEL::CellModel& _cm;
627 };
628
629 /// @endcond
630
631 /*!
632  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
633  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
634  * describing correspondence between cells of \a this and the result meshes are
635  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
636  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
637  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
638  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
639  * \warning For speed reasons, this method does not check if node ids in the nodal
640  *          connectivity correspond to the size of node coordinates array.
641  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
642  *          to write this mesh to the MED file, its cells must be sorted using
643  *          sortCellsInMEDFileFrmt().
644  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
645  *         each cell of \a this mesh.
646  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
647  *        dividing cell ids in \a desc into groups each referring to one
648  *        cell of \a this mesh. Its every element (except the last one) is an index
649  *        pointing to the first id of a group of cells. For example cells of the
650  *        result mesh bounding the cell #1 of \a this mesh are described by following
651  *        range of indices:
652  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
653  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
654  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
655  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
656  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
657  *         by each cell of the result mesh.
658  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
659  *        in the result mesh,
660  *        dividing cell ids in \a revDesc into groups each referring to one
661  *        cell of the result mesh the same way as \a descIndx divides \a desc.
662  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
663  *        delete this mesh using decrRef() as it is no more needed.
664  *  \throw If the coordinates array is not set.
665  *  \throw If the nodal connectivity of cells is node defined.
666  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
667  *         revDescIndx == NULL.
668  * 
669  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
670  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
671  * \sa buildDescendingConnectivity2()
672  */
673 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
674 {
675   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
676 }
677
678 /*!
679  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
680  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
681  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
682  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
683  * \sa MEDCouplingUMesh::buildDescendingConnectivity
684  */
685 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
686 {
687   checkFullyDefined();
688   if(getMeshDimension()!=3)
689     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
690   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
691 }
692
693 /*!
694  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
695  * this->getMeshDimension(), that bound cells of \a this mesh. In
696  * addition arrays describing correspondence between cells of \a this and the result
697  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
698  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
699  *  mesh. This method differs from buildDescendingConnectivity() in that apart
700  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
701  * result meshes. So a positive id means that order of nodes in corresponding cells
702  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
703  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
704  * i.e. cell ids are one-based.
705  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
706  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
707  * \warning For speed reasons, this method does not check if node ids in the nodal
708  *          connectivity correspond to the size of node coordinates array.
709  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710  *          to write this mesh to the MED file, its cells must be sorted using
711  *          sortCellsInMEDFileFrmt().
712  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
713  *         each cell of \a this mesh.
714  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715  *        dividing cell ids in \a desc into groups each referring to one
716  *        cell of \a this mesh. Its every element (except the last one) is an index
717  *        pointing to the first id of a group of cells. For example cells of the
718  *        result mesh bounding the cell #1 of \a this mesh are described by following
719  *        range of indices:
720  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725  *         by each cell of the result mesh.
726  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
727  *        in the result mesh,
728  *        dividing cell ids in \a revDesc into groups each referring to one
729  *        cell of the result mesh the same way as \a descIndx divides \a desc.
730  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
731  *        shares the node coordinates array with \a this mesh. The caller is to
732  *        delete this mesh using decrRef() as it is no more needed.
733  *  \throw If the coordinates array is not set.
734  *  \throw If the nodal connectivity of cells is node defined.
735  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736  *         revDescIndx == NULL.
737  * 
738  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
739  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
740  * \sa buildDescendingConnectivity()
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
743 {
744   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
745 }
746
747 /*!
748  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
749  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
750  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
751  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
752  *
753  * \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
754  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
755  * \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.
756  */
757 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
758 {
759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
763   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
764   meshDM1=0;
765   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
766 }
767
768 /*!
769  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
770  * 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,
771  * excluding a set of meshdim-1 cells in input descending connectivity.
772  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
773  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
774  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
775  *
776  * \param [in] desc descending connectivity array.
777  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
778  * \param [in] revDesc reverse descending connectivity array.
779  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
780  * \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
781  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
782  * \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.
783  */
784 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
785                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
786 {
787   if(!desc || !descIndx || !revDesc || !revDescIndx)
788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
789   const int *descPtr=desc->getConstPointer();
790   const int *descIPtr=descIndx->getConstPointer();
791   const int *revDescPtr=revDesc->getConstPointer();
792   const int *revDescIPtr=revDescIndx->getConstPointer();
793   //
794   int nbCells=descIndx->getNumberOfTuples()-1;
795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
797   int *out1Ptr=out1->getPointer();
798   *out1Ptr++=0;
799   out0->reserve(desc->getNumberOfTuples());
800   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
801     {
802       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
803         {
804           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
805           s.erase(i);
806           out0->insertAtTheEnd(s.begin(),s.end());
807         }
808       *out1Ptr=out0->getNumberOfTuples();
809     }
810   neighbors=out0.retn();
811   neighborsIndx=out1.retn();
812 }
813
814 /// @cond INTERNAL
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.
819  */
820 template<class SonsGenerator>
821 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
822 {
823   if(!desc || !descIndx || !revDesc || !revDescIndx)
824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
825   checkConnectivityFullyDefined();
826   int nbOfCells=getNumberOfCells();
827   int nbOfNodes=getNumberOfNodes();
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
829   int *revNodalIndxPtr=revNodalIndx->getPointer();
830   const int *conn=_nodal_connec->getConstPointer();
831   const int *connIndex=_nodal_connec_index->getConstPointer();
832   std::string name="Mesh constituent of "; name+=getName();
833   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
834   ret->setCoords(getCoords());
835   ret->allocateCells(2*nbOfCells);
836   descIndx->alloc(nbOfCells+1,1);
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
838   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
839   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
840     {
841       int pos=connIndex[eltId];
842       int posP1=connIndex[eltId+1];
843       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
844       SonsGenerator sg(cm);
845       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
846       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
847       for(unsigned i=0;i<nbOfSons;i++)
848         {
849           INTERP_KERNEL::NormalizedCellType cmsId;
850           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
851           for(unsigned k=0;k<nbOfNodesSon;k++)
852             if(tmp[k]>=0)
853               revNodalIndxPtr[tmp[k]+1]++;
854           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
855           revDesc2->pushBackSilent(eltId);
856         }
857       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
858     }
859   int nbOfCellsM1=ret->getNumberOfCells();
860   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
862   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
863   int *revNodalPtr=revNodal->getPointer();
864   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
865   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
866   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
867     {
868       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
869       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
870       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
871         if(*iter>=0)//for polyhedrons
872           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
873     }
874   //
875   DataArrayInt *commonCells=0,*commonCellsI=0;
876   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
878   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
879   int newNbOfCellsM1=-1;
880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
881                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
882   std::vector<bool> isImpacted(nbOfCellsM1,false);
883   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
884     for(int work2=work[0];work2!=work[1];work2++)
885       isImpacted[commonCellsPtr[work2]]=true;
886   const int *o2nM1Ptr=o2nM1->getConstPointer();
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
888   const int *n2oM1Ptr=n2oM1->getConstPointer();
889   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
890   ret2->copyTinyInfoFrom(this);
891   desc->alloc(descIndx->back(),1);
892   int *descPtr=desc->getPointer();
893   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
894   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
895     {
896       if(!isImpacted[i])
897         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
898       else
899         {
900           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
901             {
902               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
903               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
904             }
905           else
906             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
907         }
908     }
909   revDesc->reserve(newNbOfCellsM1);
910   revDescIndx->alloc(newNbOfCellsM1+1,1);
911   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
912   const int *revDesc2Ptr=revDesc2->getConstPointer();
913   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
914     {
915       int oldCellIdM1=n2oM1Ptr[i];
916       if(!isImpacted[oldCellIdM1])
917         {
918           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
919           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
920         }
921       else
922         {
923           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
924             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
925           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
926           commonCellsIPtr++;
927         }
928     }
929   //
930   return ret2.retn();
931 }
932
933 struct MEDCouplingAccVisit
934 {
935   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
936   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
937   int _new_nb_of_nodes;
938 };
939
940 /// @endcond
941
942 /*!
943  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
944  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
945  * array of cell ids. Pay attention that after conversion all algorithms work slower
946  * with \a this mesh than before conversion. <br> If an exception is thrown during the
947  * conversion due presence of invalid ids in the array of cells to convert, as a
948  * result \a this mesh contains some already converted elements. In this case the 2D
949  * mesh remains valid but 3D mesh becomes \b inconsistent!
950  *  \warning This method can significantly modify the order of geometric types in \a this,
951  *          hence, to write this mesh to the MED file, its cells must be sorted using
952  *          sortCellsInMEDFileFrmt().
953  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
954  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
955  *         cellIdsToConvertBg.
956  *  \throw If the coordinates array is not set.
957  *  \throw If the nodal connectivity of cells is node defined.
958  *  \throw If dimension of \a this mesh is not either 2 or 3.
959  *
960  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
961  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
962  */
963 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
964 {
965   checkFullyDefined();
966   int dim=getMeshDimension();
967   if(dim<2 || dim>3)
968     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
969   int nbOfCells=getNumberOfCells();
970   if(dim==2)
971     {
972       const int *connIndex=_nodal_connec_index->getConstPointer();
973       int *conn=_nodal_connec->getPointer();
974       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
975         {
976           if(*iter>=0 && *iter<nbOfCells)
977             {
978               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
979               if(!cm.isQuadratic())
980                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
981               else
982                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
983             }
984           else
985             {
986               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
987               oss << " in range [0," << nbOfCells << ") !";
988               throw INTERP_KERNEL::Exception(oss.str().c_str());
989             }
990         }
991     }
992   else
993     {
994       int *connIndex=_nodal_connec_index->getPointer();
995       int connIndexLgth=_nodal_connec_index->getNbOfElems();
996       const int *connOld=_nodal_connec->getConstPointer();
997       int connOldLgth=_nodal_connec->getNbOfElems();
998       std::vector<int> connNew(connOld,connOld+connOldLgth);
999       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1000         {
1001           if(*iter>=0 && *iter<nbOfCells)
1002             {
1003               int pos=connIndex[*iter];
1004               int posP1=connIndex[(*iter)+1];
1005               int lgthOld=posP1-pos-1;
1006               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1007               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1008               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1009               int *tmp=new int[nbOfFaces*lgthOld];
1010               int *work=tmp;
1011               for(int j=0;j<(int)nbOfFaces;j++)
1012                 {
1013                   INTERP_KERNEL::NormalizedCellType type;
1014                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1015                   work+=offset;
1016                   *work++=-1;
1017                 }
1018               std::size_t newLgth=std::distance(tmp,work)-1;
1019               std::size_t delta=newLgth-lgthOld;
1020               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1021               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1022               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1023               delete [] tmp;
1024             }
1025           else
1026             {
1027               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1028               oss << " in range [0," << nbOfCells << ") !";
1029               throw INTERP_KERNEL::Exception(oss.str().c_str());
1030             }
1031         }
1032       _nodal_connec->alloc((int)connNew.size(),1);
1033       int *newConnPtr=_nodal_connec->getPointer();
1034       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1035     }
1036   computeTypes();
1037 }
1038
1039 /*!
1040  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1041  * polyhedrons (if \a this is a 3D mesh).
1042  *  \warning As this method is purely for user-friendliness and no optimization is
1043  *          done to avoid construction of a useless vector, this method can be costly
1044  *          in memory.
1045  *  \throw If the coordinates array is not set.
1046  *  \throw If the nodal connectivity of cells is node defined.
1047  *  \throw If dimension of \a this mesh is not either 2 or 3.
1048  */
1049 void MEDCouplingUMesh::convertAllToPoly()
1050 {
1051   int nbOfCells=getNumberOfCells();
1052   std::vector<int> cellIds(nbOfCells);
1053   for(int i=0;i<nbOfCells;i++)
1054     cellIds[i]=i;
1055   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1056 }
1057
1058 /*!
1059  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1060  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1061  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1062  * base facet of the volume and the second half of nodes describes an opposite facet
1063  * having the same number of nodes as the base one. This method converts such
1064  * connectivity to a valid polyhedral format where connectivity of each facet is
1065  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1066  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1067  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1068  * a correct orientation of the first facet of a polyhedron, else orientation of a
1069  * corrected cell is reverse.<br>
1070  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1071  * it releases the user from boring description of polyhedra connectivity in the valid
1072  * format.
1073  *  \throw If \a this->getMeshDimension() != 3.
1074  *  \throw If \a this->getSpaceDimension() != 3.
1075  *  \throw If the nodal connectivity of cells is not defined.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1078  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1079  *
1080  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1081  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1082  */
1083 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1084 {
1085   checkFullyDefined();
1086   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1088   int nbOfCells=getNumberOfCells();
1089   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1090   newCi->alloc(nbOfCells+1,1);
1091   int *newci=newCi->getPointer();
1092   const int *ci=_nodal_connec_index->getConstPointer();
1093   const int *c=_nodal_connec->getConstPointer();
1094   newci[0]=0;
1095   for(int i=0;i<nbOfCells;i++)
1096     {
1097       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1098       if(type==INTERP_KERNEL::NORM_POLYHED)
1099         {
1100           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1101             {
1102               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1106           if(n2%2!=0)
1107             {
1108               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 !";
1109               throw INTERP_KERNEL::Exception(oss.str().c_str());
1110             }
1111           int n1=(int)(n2/2);
1112           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)
1113         }
1114       else
1115         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1116     }
1117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1118   newC->alloc(newci[nbOfCells],1);
1119   int *newc=newC->getPointer();
1120   for(int i=0;i<nbOfCells;i++)
1121     {
1122       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1123       if(type==INTERP_KERNEL::NORM_POLYHED)
1124         {
1125           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1126           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1127           *newc++=-1;
1128           for(std::size_t j=0;j<n1;j++)
1129             {
1130               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1131               newc[n1+5*j]=-1;
1132               newc[n1+5*j+1]=c[ci[i]+1+j];
1133               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1134               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1135               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1136             }
1137           newc+=n1*6;
1138         }
1139       else
1140         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1141     }
1142   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1143   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1144 }
1145
1146
1147 /*!
1148  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1149  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1150  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1151  *          to write this mesh to the MED file, its cells must be sorted using
1152  *          sortCellsInMEDFileFrmt().
1153  * \return \c true if at least one cell has been converted, \c false else. In the
1154  *         last case the nodal connectivity remains unchanged.
1155  * \throw If the coordinates array is not set.
1156  * \throw If the nodal connectivity of cells is not defined.
1157  * \throw If \a this->getMeshDimension() < 0.
1158  */
1159 bool MEDCouplingUMesh::unPolyze()
1160 {
1161   checkFullyDefined();
1162   int mdim=getMeshDimension();
1163   if(mdim<0)
1164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1165   if(mdim<=1)
1166     return false;
1167   int nbOfCells=getNumberOfCells();
1168   if(nbOfCells<1)
1169     return false;
1170   int initMeshLgth=getMeshLength();
1171   int *conn=_nodal_connec->getPointer();
1172   int *index=_nodal_connec_index->getPointer();
1173   int posOfCurCell=0;
1174   int newPos=0;
1175   int lgthOfCurCell;
1176   bool ret=false;
1177   for(int i=0;i<nbOfCells;i++)
1178     {
1179       lgthOfCurCell=index[i+1]-posOfCurCell;
1180       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1181       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1182       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1183       int newLgth;
1184       if(cm.isDynamic())
1185         {
1186           switch(cm.getDimension())
1187             {
1188             case 2:
1189               {
1190                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1191                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1192                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1193                 break;
1194               }
1195             case 3:
1196               {
1197                 int nbOfFaces,lgthOfPolyhConn;
1198                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1199                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1200                 break;
1201               }
1202             case 1:
1203               {
1204                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1205                 break;
1206               }
1207             }
1208           ret=ret || (newType!=type);
1209           conn[newPos]=newType;
1210           newPos+=newLgth+1;
1211           posOfCurCell=index[i+1];
1212           index[i+1]=newPos;
1213         }
1214       else
1215         {
1216           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1217           newPos+=lgthOfCurCell;
1218           posOfCurCell+=lgthOfCurCell;
1219           index[i+1]=newPos;
1220         }
1221     }
1222   if(newPos!=initMeshLgth)
1223     _nodal_connec->reAlloc(newPos);
1224   if(ret)
1225     computeTypes();
1226   return ret;
1227 }
1228
1229 /*!
1230  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1231  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1232  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1233  *
1234  * \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 
1235  *             precision.
1236  */
1237 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1238 {
1239   checkFullyDefined();
1240   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1243   coords->recenterForMaxPrecision(eps);
1244   //
1245   int nbOfCells=getNumberOfCells();
1246   const int *conn=_nodal_connec->getConstPointer();
1247   const int *index=_nodal_connec_index->getConstPointer();
1248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1249   connINew->alloc(nbOfCells+1,1);
1250   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1252   bool changed=false;
1253   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1254     {
1255       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1256         {
1257           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1258           changed=true;
1259         }
1260       else
1261         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1262       *connINewPtr=connNew->getNumberOfTuples();
1263     }
1264   if(changed)
1265     setConnectivity(connNew,connINew,false);
1266 }
1267
1268 /*!
1269  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1270  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1271  * the format of returned DataArrayInt instance.
1272  * 
1273  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1274  * \sa MEDCouplingUMesh::getNodeIdsInUse
1275  */
1276 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1277 {
1278   checkConnectivityFullyDefined();
1279   int nbOfCells=getNumberOfCells();
1280   const int *connIndex=_nodal_connec_index->getConstPointer();
1281   const int *conn=_nodal_connec->getConstPointer();
1282   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1283   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1284   std::vector<bool> retS(maxElt,false);
1285   for(int i=0;i<nbOfCells;i++)
1286     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1287       if(conn[j]>=0)
1288         retS[conn[j]]=true;
1289   int sz=0;
1290   for(int i=0;i<maxElt;i++)
1291     if(retS[i])
1292       sz++;
1293   DataArrayInt *ret=DataArrayInt::New();
1294   ret->alloc(sz,1);
1295   int *retPtr=ret->getPointer();
1296   for(int i=0;i<maxElt;i++)
1297     if(retS[i])
1298       *retPtr++=i;
1299   return ret;
1300 }
1301
1302 /*!
1303  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1304  * \sa MEDCouplingUMesh::getNodeIdsInUse
1305  */
1306 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1307 {
1308   int nbOfNodes=(int)nodeIdsInUse.size();
1309   int nbOfCells=getNumberOfCells();
1310   const int *connIndex=_nodal_connec_index->getConstPointer();
1311   const int *conn=_nodal_connec->getConstPointer();
1312   for(int i=0;i<nbOfCells;i++)
1313     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1314       if(conn[j]>=0)
1315         {
1316           if(conn[j]<nbOfNodes)
1317             nodeIdsInUse[conn[j]]=true;
1318           else
1319             {
1320               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1321               throw INTERP_KERNEL::Exception(oss.str().c_str());
1322             }
1323         }
1324 }
1325
1326 /*!
1327  * Finds nodes not used in any cell and returns an array giving a new id to every node
1328  * by excluding the unused nodes, for which the array holds -1. The result array is
1329  * a mapping in "Old to New" mode. 
1330  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1331  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1332  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1333  *          if the node is unused or a new id else. The caller is to delete this
1334  *          array using decrRef() as it is no more needed.  
1335  *  \throw If the coordinates array is not set.
1336  *  \throw If the nodal connectivity of cells is not defined.
1337  *  \throw If the nodal connectivity includes an invalid id.
1338  *
1339  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1340  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1341  * \sa computeNodeIdsAlg()
1342  */
1343 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1344 {
1345   nbrOfNodesInUse=-1;
1346   int nbOfNodes=getNumberOfNodes();
1347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1348   ret->alloc(nbOfNodes,1);
1349   int *traducer=ret->getPointer();
1350   std::fill(traducer,traducer+nbOfNodes,-1);
1351   int nbOfCells=getNumberOfCells();
1352   const int *connIndex=_nodal_connec_index->getConstPointer();
1353   const int *conn=_nodal_connec->getConstPointer();
1354   for(int i=0;i<nbOfCells;i++)
1355     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1356       if(conn[j]>=0)
1357         {
1358           if(conn[j]<nbOfNodes)
1359             traducer[conn[j]]=1;
1360           else
1361             {
1362               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1363               throw INTERP_KERNEL::Exception(oss.str().c_str());
1364             }
1365         }
1366   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1367   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1368   return ret.retn();
1369 }
1370
1371 /*!
1372  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1373  * For each cell in \b this the number of nodes constituting cell is computed.
1374  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1375  * So for pohyhedrons some nodes can be counted several times in the returned result.
1376  * 
1377  * \return a newly allocated array
1378  */
1379 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1380 {
1381   checkConnectivityFullyDefined();
1382   int nbOfCells=getNumberOfCells();
1383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1384   ret->alloc(nbOfCells,1);
1385   int *retPtr=ret->getPointer();
1386   const int *conn=getNodalConnectivity()->getConstPointer();
1387   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1388   for(int i=0;i<nbOfCells;i++,retPtr++)
1389     {
1390       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1391         *retPtr=connI[i+1]-connI[i]-1;
1392       else
1393         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1394     }
1395   return ret.retn();
1396 }
1397
1398 /*!
1399  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1400  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1401  * 
1402  * \return a newly allocated array
1403  */
1404 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1405 {
1406   checkConnectivityFullyDefined();
1407   int nbOfCells=getNumberOfCells();
1408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1409   ret->alloc(nbOfCells,1);
1410   int *retPtr=ret->getPointer();
1411   const int *conn=getNodalConnectivity()->getConstPointer();
1412   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1413   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1414     {
1415       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1416       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1417     }
1418   return ret.retn();
1419 }
1420
1421 /*!
1422  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1423  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1424  * array mean that the corresponding old node is no more used. 
1425  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1426  *           this->getNumberOfNodes() before call of this method. The caller is to
1427  *           delete this array using decrRef() as it is no more needed. 
1428  *  \throw If the coordinates array is not set.
1429  *  \throw If the nodal connectivity of cells is not defined.
1430  *  \throw If the nodal connectivity includes an invalid id.
1431  *
1432  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1433  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1434  */
1435 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1436 {
1437   int newNbOfNodes=-1;
1438   DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1439   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1440   return traducer;
1441 }
1442
1443 /*!
1444  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1445  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1446  */
1447 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1448 {
1449   switch(compType)
1450     {
1451     case 0:
1452       return AreCellsEqual0(conn,connI,cell1,cell2);
1453     case 1:
1454       return AreCellsEqual1(conn,connI,cell1,cell2);
1455     case 2:
1456       return AreCellsEqual2(conn,connI,cell1,cell2);
1457     case 3:
1458       return AreCellsEqual3(conn,connI,cell1,cell2);
1459     case 7:
1460       return AreCellsEqual7(conn,connI,cell1,cell2);
1461     }
1462   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1463 }
1464
1465 /*!
1466  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1467  */
1468 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1469 {
1470   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1471     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1472   return 0;
1473 }
1474
1475 /*!
1476  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1477  */
1478 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1479 {
1480   int sz=connI[cell1+1]-connI[cell1];
1481   if(sz==connI[cell2+1]-connI[cell2])
1482     {
1483       if(conn[connI[cell1]]==conn[connI[cell2]])
1484         {
1485           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1486           unsigned dim=cm.getDimension();
1487           if(dim!=3)
1488             {
1489               if(dim!=1)
1490                 {
1491                   int sz1=2*(sz-1);
1492                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1493                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1494                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1495                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1496                   return work!=tmp+sz1?1:0;
1497                 }
1498               else
1499                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1500             }
1501           else
1502             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1503         }
1504     }
1505   return 0;
1506 }
1507
1508 /*!
1509  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1510  */
1511 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1512 {
1513   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1514     {
1515       if(conn[connI[cell1]]==conn[connI[cell2]])
1516         {
1517           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1518           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1519           return s1==s2?1:0;
1520         }
1521     }
1522   return 0;
1523 }
1524
1525 /*!
1526  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1527  */
1528 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1529 {
1530   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1531     {
1532       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1533       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1534       return s1==s2?1:0;
1535     }
1536   return 0;
1537 }
1538
1539 /*!
1540  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1541  */
1542 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1543 {
1544   int sz=connI[cell1+1]-connI[cell1];
1545   if(sz==connI[cell2+1]-connI[cell2])
1546     {
1547       if(conn[connI[cell1]]==conn[connI[cell2]])
1548         {
1549           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1550           unsigned dim=cm.getDimension();
1551           if(dim!=3)
1552             {
1553               if(dim!=1)
1554                 {
1555                   int sz1=2*(sz-1);
1556                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1557                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1558                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1559                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1560                   if(work!=tmp+sz1)
1561                     return 1;
1562                   else
1563                     {
1564                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1565                       std::reverse_iterator<int *> it2((int *)tmp);
1566                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1567                         return 2;
1568                       else
1569                         return 0;
1570                     }
1571                   
1572                   return work!=tmp+sz1?1:0;
1573                 }
1574               else
1575                 {//case of SEG2 and SEG3
1576                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1577                     return 1;
1578                   if(!cm.isQuadratic())
1579                     {
1580                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1581                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1582                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1583                         return 2;
1584                       return 0;
1585                     }
1586                   else
1587                     {
1588                       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])
1589                         return 2;
1590                       return 0;
1591                     }
1592                 }
1593             }
1594           else
1595             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1596         }
1597     }
1598   return 0;
1599 }
1600
1601 /*!
1602  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1603  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1604  * and result remains unchanged.
1605  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1606  * If in 'candidates' pool -1 value is considered as an empty value.
1607  * WARNING this method returns only ONE set of result !
1608  */
1609 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1610 {
1611   if(candidates.size()<1)
1612     return false;
1613   bool ret=false;
1614   std::vector<int>::const_iterator iter=candidates.begin();
1615   int start=(*iter++);
1616   for(;iter!=candidates.end();iter++)
1617     {
1618       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1619       if(status!=0)
1620         {
1621           if(!ret)
1622             {
1623               result->pushBackSilent(start);
1624               ret=true;
1625             }
1626           if(status==1)
1627             result->pushBackSilent(*iter);
1628           else
1629             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1630         }
1631     }
1632   return ret;
1633 }
1634
1635 /*!
1636  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1637  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1638  *
1639  * \param [in] compType input specifying the technique used to compare cells each other.
1640  *   - 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.
1641  *   - 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)
1642  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1643  *   - 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
1644  * can be used for users not sensitive to orientation of cell
1645  * \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.
1646  * \param [out] commonCells
1647  * \param [out] commonCellsI
1648  * \return the correspondance array old to new in a newly allocated array.
1649  * 
1650  */
1651 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1652 {
1653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1654   getReverseNodalConnectivity(revNodal,revNodalI);
1655   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1656 }
1657
1658 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1659                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1660 {
1661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1662   int nbOfCells=nodalI->getNumberOfTuples()-1;
1663   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1664   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1665   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1666   std::vector<bool> isFetched(nbOfCells,false);
1667   if(startCellId==0)
1668     {
1669       for(int i=0;i<nbOfCells;i++)
1670         {
1671           if(!isFetched[i])
1672             {
1673               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1674               std::vector<int> v,v2;
1675               if(connOfNode!=connPtr+connIPtr[i+1])
1676                 {
1677                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1678                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1679                   connOfNode++;
1680                 }
1681               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1682                 if(*connOfNode>=0)
1683                   {
1684                     v=v2;
1685                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1686                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1687                     v2.resize(std::distance(v2.begin(),it));
1688                   }
1689               if(v2.size()>1)
1690                 {
1691                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1692                     {
1693                       int pos=commonCellsI->back();
1694                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1695                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1696                         isFetched[*it]=true;
1697                     }
1698                 }
1699             }
1700         }
1701     }
1702   else
1703     {
1704       for(int i=startCellId;i<nbOfCells;i++)
1705         {
1706           if(!isFetched[i])
1707             {
1708               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1709               std::vector<int> v,v2;
1710               if(connOfNode!=connPtr+connIPtr[i+1])
1711                 {
1712                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1713                   connOfNode++;
1714                 }
1715               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1716                 if(*connOfNode>=0)
1717                   {
1718                     v=v2;
1719                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1720                     v2.resize(std::distance(v2.begin(),it));
1721                   }
1722               if(v2.size()>1)
1723                 {
1724                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1725                     {
1726                       int pos=commonCellsI->back();
1727                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1728                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1729                         isFetched[*it]=true;
1730                     }
1731                 }
1732             }
1733         }
1734     }
1735   commonCellsArr=commonCells.retn();
1736   commonCellsIArr=commonCellsI.retn();
1737 }
1738
1739 /*!
1740  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1741  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1742  * than \a other->getNumberOfCells() in the returned array means that there is no
1743  * corresponding cell in \a this mesh.
1744  * It is expected that \a this and \a other meshes share the same node coordinates
1745  * array, if it is not so an exception is thrown. 
1746  *  \param [in] other - the mesh to compare with.
1747  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1748  *         valid values [0,1,2], see zipConnectivityTraducer().
1749  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1750  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1751  *         values. The caller is to delete this array using
1752  *         decrRef() as it is no more needed.
1753  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1754  *         mesh.
1755  *
1756  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1757  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1758  *  \sa checkDeepEquivalOnSameNodesWith()
1759  *  \sa checkGeoEquivalWith()
1760  */
1761 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1762 {
1763   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1764   int nbOfCells=getNumberOfCells();
1765   static const int possibleCompType[]={0,1,2};
1766   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1767     {
1768       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1769       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1770       oss << " !";
1771       throw INTERP_KERNEL::Exception(oss.str().c_str());
1772     }
1773   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1774   arr=o2n->substr(nbOfCells);
1775   arr->setName(other->getName());
1776   int tmp;
1777   if(other->getNumberOfCells()==0)
1778     return true;
1779   return arr->getMaxValue(tmp)<nbOfCells;
1780 }
1781
1782 /*!
1783  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1784  * This method tries to determine if \b other is fully included in \b this.
1785  * The main difference is that this method is not expected to throw exception.
1786  * This method has two outputs :
1787  *
1788  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1789  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1790  */
1791 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1792 {
1793   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1794   DataArrayInt *commonCells=0,*commonCellsI=0;
1795   int thisNbCells=getNumberOfCells();
1796   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1798   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1799   int otherNbCells=other->getNumberOfCells();
1800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1801   arr2->alloc(otherNbCells,1);
1802   arr2->fillWithZero();
1803   int *arr2Ptr=arr2->getPointer();
1804   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1805   for(int i=0;i<nbOfCommon;i++)
1806     {
1807       int start=commonCellsPtr[commonCellsIPtr[i]];
1808       if(start<thisNbCells)
1809         {
1810           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1811             {
1812               int sig=commonCellsPtr[j]>0?1:-1;
1813               int val=std::abs(commonCellsPtr[j])-1;
1814               if(val>=thisNbCells)
1815                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1816             }
1817         }
1818     }
1819   arr2->setName(other->getName());
1820   if(arr2->presenceOfValue(0))
1821     return false;
1822   arr=arr2.retn();
1823   return true;
1824 }
1825
1826 /*!
1827  * Merges nodes equal within \a precision and returns an array describing the 
1828  * permutation used to remove duplicate nodes.
1829  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1830  *              considered not coincident.
1831  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1832  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1833  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1834  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1835  *          is to delete this array using decrRef() as it is no more needed.
1836  *  \throw If the coordinates array is not set.
1837  *  \throw If the nodal connectivity of cells is not defined.
1838  *
1839  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1840  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1841  */
1842 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1843 {
1844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1845   if(areNodesMerged)
1846     renumberNodes(ret->begin(),newNbOfNodes);
1847   return ret.retn();
1848 }
1849
1850
1851 /*!
1852  * Merges nodes equal within \a precision and returns an array describing the 
1853  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1854  *  of merged nodes is changed to be at their barycenter.
1855  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1856  *              considered not coincident.
1857  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1858  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1859  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1860  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1861  *          is to delete this array using decrRef() as it is no more needed.
1862  *  \throw If the coordinates array is not set.
1863  *  \throw If the nodal connectivity of cells is not defined.
1864  *
1865  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1866  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1867  */
1868 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1869 {
1870   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1871   if(areNodesMerged)
1872     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1873   return ret;
1874 }
1875
1876 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1877 {
1878   if(!other)
1879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1880   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1881   if(!otherC)
1882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1883   std::vector<const MEDCouplingUMesh *> ms(2);
1884   ms[0]=this;
1885   ms[1]=otherC;
1886   return MergeUMeshesOnSameCoords(ms);
1887 }
1888
1889 /*!
1890  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1891  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1892  * cellIds is not given explicitely but by a range python like.
1893  * 
1894  * \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.
1895  * \return a newly allocated
1896  * 
1897  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1898  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1899  */
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1901 {
1902   if(getMeshDimension()!=-1)
1903     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1904   else
1905     {
1906       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1907       if(newNbOfCells!=1)
1908         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1909       if(start!=0)
1910         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1911       incrRef();
1912       return const_cast<MEDCouplingUMesh *>(this);
1913     }
1914 }
1915
1916 /*!
1917  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1918  * The result mesh shares or not the node coordinates array with \a this mesh depending
1919  * on \a keepCoords parameter.
1920  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1921  *           to write this mesh to the MED file, its cells must be sorted using
1922  *           sortCellsInMEDFileFrmt().
1923  *  \param [in] begin - an array of cell ids to include to the new mesh.
1924  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1925  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1926  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1927  *         by calling zipCoords().
1928  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1929  *         to delete this mesh using decrRef() as it is no more needed. 
1930  *  \throw If the coordinates array is not set.
1931  *  \throw If the nodal connectivity of cells is not defined.
1932  *  \throw If any cell id in the array \a begin is not valid.
1933  *
1934  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1935  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1936  */
1937 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1938 {
1939   if(getMeshDimension()!=-1)
1940     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1941   else
1942     {
1943       if(end-begin!=1)
1944         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1945       if(begin[0]!=0)
1946         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1947       incrRef();
1948       return const_cast<MEDCouplingUMesh *>(this);
1949     }
1950 }
1951
1952 /*!
1953  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1954  *
1955  * 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.
1956  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1957  * The number of cells of \b this will remain the same with this method.
1958  *
1959  * \param [in] begin begin of cell ids (included) of cells in this to assign
1960  * \param [in] end end of cell ids (excluded) of cells in this to assign
1961  * \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 ).
1962  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1963  */
1964 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1965 {
1966   checkConnectivityFullyDefined();
1967   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1968   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1970   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1971     {
1972       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1973       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1974       throw INTERP_KERNEL::Exception(oss.str().c_str());
1975     }
1976   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1977   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1978     {
1979       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1980       throw INTERP_KERNEL::Exception(oss.str().c_str());
1981     }
1982   int nbOfCells=getNumberOfCells();
1983   bool easyAssign=true;
1984   const int *connI=_nodal_connec_index->getConstPointer();
1985   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1986   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1987     {
1988       if(*it>=0 && *it<nbOfCells)
1989         {
1990           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1991         }
1992       else
1993         {
1994           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1995           throw INTERP_KERNEL::Exception(oss.str().c_str());
1996         }
1997     }
1998   if(easyAssign)
1999     {
2000       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2001       computeTypes();
2002     }
2003   else
2004     {
2005       DataArrayInt *arrOut=0,*arrIOut=0;
2006       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2007                                                arrOut,arrIOut);
2008       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2009       setConnectivity(arrOut,arrIOut,true);
2010     }
2011 }
2012
2013 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2014 {
2015   checkConnectivityFullyDefined();
2016   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2017   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2019   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2020     {
2021       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2022       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2023       throw INTERP_KERNEL::Exception(oss.str().c_str());
2024     }
2025   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2026   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2027     {
2028       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2029       throw INTERP_KERNEL::Exception(oss.str().c_str());
2030     }
2031   int nbOfCells=getNumberOfCells();
2032   bool easyAssign=true;
2033   const int *connI=_nodal_connec_index->getConstPointer();
2034   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2035   int it=start;
2036   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2037     {
2038       if(it>=0 && it<nbOfCells)
2039         {
2040           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2041         }
2042       else
2043         {
2044           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2045           throw INTERP_KERNEL::Exception(oss.str().c_str());
2046         }
2047     }
2048   if(easyAssign)
2049     {
2050       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2051       computeTypes();
2052     }
2053   else
2054     {
2055       DataArrayInt *arrOut=0,*arrIOut=0;
2056       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2057                                                 arrOut,arrIOut);
2058       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2059       setConnectivity(arrOut,arrIOut,true);
2060     }
2061 }                      
2062
2063 /*!
2064  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2065  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2066  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2067  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2068  *
2069  * \param [in] begin input start of array of node ids.
2070  * \param [in] end input end of array of node ids.
2071  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2072  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2073  */
2074 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2075 {
2076   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2077   checkConnectivityFullyDefined();
2078   int tmp=-1;
2079   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2080   std::vector<bool> fastFinder(sz,false);
2081   for(const int *work=begin;work!=end;work++)
2082     if(*work>=0 && *work<sz)
2083       fastFinder[*work]=true;
2084   int nbOfCells=getNumberOfCells();
2085   const int *conn=getNodalConnectivity()->getConstPointer();
2086   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2087   for(int i=0;i<nbOfCells;i++)
2088     {
2089       int ref=0,nbOfHit=0;
2090       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2091         if(*work2>=0)
2092           {
2093             ref++;
2094             if(fastFinder[*work2])
2095               nbOfHit++;
2096           }
2097       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2098         cellIdsKept->pushBackSilent(i);
2099     }
2100   cellIdsKeptArr=cellIdsKept.retn();
2101 }
2102
2103 /*!
2104  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2105  * this->getMeshDimension(), that bound some cells of \a this mesh.
2106  * The cells of lower dimension to include to the result mesh are selected basing on
2107  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2108  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2109  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2110  * created mesh shares the node coordinates array with \a this mesh. 
2111  *  \param [in] begin - the array of node ids.
2112  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2113  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2114  *         array \a begin are added, else cells whose any node is in the
2115  *         array \a begin are added.
2116  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2117  *         to delete this mesh using decrRef() as it is no more needed. 
2118  *  \throw If the coordinates array is not set.
2119  *  \throw If the nodal connectivity of cells is not defined.
2120  *  \throw If any node id in \a begin is not valid.
2121  *
2122  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2123  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2124  */
2125 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2126 {
2127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2128   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2129   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2130   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2131   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2132 }
2133
2134 /*!
2135  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2136  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2137  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2138  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2139  *         by calling zipCoords().
2140  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2141  *         to delete this mesh using decrRef() as it is no more needed. 
2142  *  \throw If the coordinates array is not set.
2143  *  \throw If the nodal connectivity of cells is not defined.
2144  *
2145  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2146  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2147  */
2148 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2149 {
2150   DataArrayInt *desc=DataArrayInt::New();
2151   DataArrayInt *descIndx=DataArrayInt::New();
2152   DataArrayInt *revDesc=DataArrayInt::New();
2153   DataArrayInt *revDescIndx=DataArrayInt::New();
2154   //
2155   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2156   revDesc->decrRef();
2157   desc->decrRef();
2158   descIndx->decrRef();
2159   int nbOfCells=meshDM1->getNumberOfCells();
2160   const int *revDescIndxC=revDescIndx->getConstPointer();
2161   std::vector<int> boundaryCells;
2162   for(int i=0;i<nbOfCells;i++)
2163     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2164       boundaryCells.push_back(i);
2165   revDescIndx->decrRef();
2166   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2167   return ret;
2168 }
2169
2170 /*!
2171  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2172  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2173  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2174  */
2175 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2176 {
2177   checkFullyDefined();
2178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2182   //
2183   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2184   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2185   //
2186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2188   const int *revDescPtr=revDesc->getConstPointer();
2189   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2190   int nbOfCells=getNumberOfCells();
2191   std::vector<bool> ret1(nbOfCells,false);
2192   int sz=0;
2193   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2194     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2195       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2196   //
2197   DataArrayInt *ret2=DataArrayInt::New();
2198   ret2->alloc(sz,1);
2199   int *ret2Ptr=ret2->getPointer();
2200   sz=0;
2201   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2202     if(*it)
2203       *ret2Ptr++=sz;
2204   ret2->setName("BoundaryCells");
2205   return ret2;
2206 }
2207
2208 /*!
2209  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2210  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2211  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2212  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2213  *
2214  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2215  * This method method returns cells ids set s = s1 + s2 where :
2216  * 
2217  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2218  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2219  *
2220  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2221  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2222  *
2223  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2224  * \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
2225  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2226  */
2227 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2228 {
2229   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2230     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2231   checkConnectivityFullyDefined();
2232   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2233   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2237   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2239   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2240   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2241   DataArrayInt *idsOtherInConsti=0;
2242   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2244   if(!b)
2245     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2246   std::set<int> s1;
2247   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2248     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2251   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2252   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2254   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2255   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2256   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2257   neighThisPartAuto=0;
2258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2259   const int li[2]={0,1};
2260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2261   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2263   s_renum1->sort();
2264   //
2265   cellIdsRk0=s0arr.retn();
2266   cellIdsRk1=s_renum1.retn();
2267 }
2268
2269 /*!
2270  * 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
2271  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2272  * 
2273  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2274  */
2275 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2276 {
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2281   //
2282   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2283   revDesc=0; desc=0; descIndx=0;
2284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2286   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2287 }
2288
2289 /*!
2290  * Finds nodes lying on the boundary of \a this mesh.
2291  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2292  *          nodes. The caller is to delete this array using decrRef() as it is no
2293  *          more needed.
2294  *  \throw If the coordinates array is not set.
2295  *  \throw If the nodal connectivity of cells is node defined.
2296  *
2297  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2298  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2299  */
2300 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2301 {
2302   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2303   return skin->computeFetchedNodeIds();
2304 }
2305
2306 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2307 {
2308   incrRef();
2309   return const_cast<MEDCouplingUMesh *>(this);
2310 }
2311
2312 /*!
2313  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2314  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2315  * 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.
2316  * 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.
2317  * 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.
2318  *
2319  * \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
2320  *             parameter is altered during the call.
2321  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2322  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2323  * \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.
2324  *
2325  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2326  */
2327 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2328                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2329 {
2330   checkFullyDefined();
2331   otherDimM1OnSameCoords.checkFullyDefined();
2332   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2334   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2336   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2337   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2340   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2341   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2345   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2346   //
2347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2350   DataArrayInt *idsTmp=0;
2351   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2353   if(!b)
2354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2355   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2356   DataArrayInt *tmp0=0,*tmp1=0;
2357   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2362   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2363   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2364   //
2365   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2366   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2367   nodeIdsToDuplicate=s3.retn();
2368 }
2369
2370 /*!
2371  * This method operates a modification of the connectivity and coords in \b this.
2372  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2373  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2374  * 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
2375  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2376  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2377  * 
2378  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2379  * 
2380  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2381  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2382  */
2383 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2384 {
2385   int nbOfNodes=getNumberOfNodes();
2386   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2387   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2388 }
2389
2390 /*!
2391  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2392  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2393  * This method is a generalization of shiftNodeNumbersInConn().
2394  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2395  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2396  *         this->getNumberOfNodes(), in "Old to New" mode. 
2397  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2398  *  \throw If the nodal connectivity of cells is not defined.
2399  *
2400  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2401  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2402  */
2403 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2404 {
2405   checkConnectivityFullyDefined();
2406   int *conn=getNodalConnectivity()->getPointer();
2407   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2408   int nbOfCells=getNumberOfCells();
2409   for(int i=0;i<nbOfCells;i++)
2410     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2411       {
2412         int& node=conn[iconn];
2413         if(node>=0)//avoid polyhedron separator
2414           {
2415             node=newNodeNumbersO2N[node];
2416           }
2417       }
2418   _nodal_connec->declareAsNew();
2419   updateTime();
2420 }
2421
2422 /*!
2423  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2424  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2425  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2426  * 
2427  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2428  */
2429 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2430 {
2431   checkConnectivityFullyDefined();
2432   int *conn=getNodalConnectivity()->getPointer();
2433   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2434   int nbOfCells=getNumberOfCells();
2435   for(int i=0;i<nbOfCells;i++)
2436     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2437       {
2438         int& node=conn[iconn];
2439         if(node>=0)//avoid polyhedron separator
2440           {
2441             node+=delta;
2442           }
2443       }
2444   _nodal_connec->declareAsNew();
2445   updateTime();
2446 }
2447
2448 /*!
2449  * This method operates a modification of the connectivity in \b this.
2450  * 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.
2451  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2452  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2453  * 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
2454  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2455  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2456  * 
2457  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2458  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2459  * 
2460  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2461  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2462  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2463  */
2464 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2465 {
2466   checkConnectivityFullyDefined();
2467   std::map<int,int> m;
2468   int val=offset;
2469   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2470     m[*work]=val;
2471   int *conn=getNodalConnectivity()->getPointer();
2472   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2473   int nbOfCells=getNumberOfCells();
2474   for(int i=0;i<nbOfCells;i++)
2475     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2476       {
2477         int& node=conn[iconn];
2478         if(node>=0)//avoid polyhedron separator
2479           {
2480             std::map<int,int>::iterator it=m.find(node);
2481             if(it!=m.end())
2482               node=(*it).second;
2483           }
2484       }
2485   updateTime();
2486 }
2487
2488 /*!
2489  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2490  *
2491  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2492  * After the call of this method the number of cells remains the same as before.
2493  *
2494  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2495  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2496  * be strictly in [0;this->getNumberOfCells()).
2497  *
2498  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2499  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2500  * should be contained in[0;this->getNumberOfCells()).
2501  * 
2502  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2503  */
2504 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2505 {
2506   checkConnectivityFullyDefined();
2507   int nbCells=getNumberOfCells();
2508   const int *array=old2NewBg;
2509   if(check)
2510     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2511   //
2512   const int *conn=_nodal_connec->getConstPointer();
2513   const int *connI=_nodal_connec_index->getConstPointer();
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2516   const int *n2oPtr=n2o->begin();
2517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2518   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2519   newConn->copyStringInfoFrom(*_nodal_connec);
2520   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2521   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2522   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2523   //
2524   int *newC=newConn->getPointer();
2525   int *newCI=newConnI->getPointer();
2526   int loc=0;
2527   newCI[0]=loc;
2528   for(int i=0;i<nbCells;i++)
2529     {
2530       int pos=n2oPtr[i];
2531       int nbOfElts=connI[pos+1]-connI[pos];
2532       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2533       loc+=nbOfElts;
2534       newCI[i+1]=loc;
2535     }
2536   //
2537   setConnectivity(newConn,newConnI);
2538   if(check)
2539     free(const_cast<int *>(array));
2540 }
2541
2542 /*!
2543  * Finds cells whose bounding boxes intersect a given bounding box.
2544  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2545  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2546  *         zMax (if in 3D). 
2547  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2548  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2549  *         extent of the bounding box of cell to produce an addition to this bounding box.
2550  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2551  *         cells. The caller is to delete this array using decrRef() as it is no more
2552  *         needed. 
2553  *  \throw If the coordinates array is not set.
2554  *  \throw If the nodal connectivity of cells is not defined.
2555  *
2556  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2557  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2558  */
2559 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2560 {
2561   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2562   if(getMeshDimension()==-1)
2563     {
2564       elems->pushBackSilent(0);
2565       return elems.retn();
2566     }
2567   int dim=getSpaceDimension();
2568   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2569   const int* conn      = getNodalConnectivity()->getConstPointer();
2570   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2571   const double* coords = getCoords()->getConstPointer();
2572   int nbOfCells=getNumberOfCells();
2573   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2574     {
2575       for (int i=0; i<dim; i++)
2576         {
2577           elem_bb[i*2]=std::numeric_limits<double>::max();
2578           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2579         }
2580
2581       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2582         {
2583           int node= conn[inode];
2584           if(node>=0)//avoid polyhedron separator
2585             {
2586               for (int idim=0; idim<dim; idim++)
2587                 {
2588                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2589                     {
2590                       elem_bb[idim*2] = coords[node*dim+idim] ;
2591                     }
2592                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2593                     {
2594                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2595                     }
2596                 }
2597             }
2598         }
2599       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2600         elems->pushBackSilent(ielem);
2601     }
2602   return elems.retn();
2603 }
2604
2605 /*!
2606  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2607  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2608  * added in 'elems' parameter.
2609  */
2610 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2611 {
2612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2613   if(getMeshDimension()==-1)
2614     {
2615       elems->pushBackSilent(0);
2616       return elems.retn();
2617     }
2618   int dim=getSpaceDimension();
2619   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2620   const int* conn      = getNodalConnectivity()->getConstPointer();
2621   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2622   const double* coords = getCoords()->getConstPointer();
2623   int nbOfCells=getNumberOfCells();
2624   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2625     {
2626       for (int i=0; i<dim; i++)
2627         {
2628           elem_bb[i*2]=std::numeric_limits<double>::max();
2629           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2630         }
2631
2632       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2633         {
2634           int node= conn[inode];
2635           if(node>=0)//avoid polyhedron separator
2636             {
2637               for (int idim=0; idim<dim; idim++)
2638                 {
2639                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2640                     {
2641                       elem_bb[idim*2] = coords[node*dim+idim] ;
2642                     }
2643                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2644                     {
2645                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2646                     }
2647                 }
2648             }
2649         }
2650       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2651         elems->pushBackSilent(ielem);
2652     }
2653   return elems.retn();
2654 }
2655
2656 /*!
2657  * Returns a type of a cell by its id.
2658  *  \param [in] cellId - the id of the cell of interest.
2659  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2660  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2661  */
2662 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2663 {
2664   const int *ptI=_nodal_connec_index->getConstPointer();
2665   const int *pt=_nodal_connec->getConstPointer();
2666   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2667     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2668   else
2669     {
2670       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2671       throw INTERP_KERNEL::Exception(oss.str().c_str());
2672     }
2673 }
2674
2675 /*!
2676  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2677  * This method does not throw exception if geometric type \a type is not in \a this.
2678  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2679  * The coordinates array is not considered here.
2680  *
2681  * \param [in] type the geometric type
2682  * \return cell ids in this having geometric type \a type.
2683  */
2684 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2685 {
2686   
2687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2688   ret->alloc(0,1);
2689   checkConnectivityFullyDefined();
2690   int nbCells=getNumberOfCells();
2691   int mdim=getMeshDimension();
2692   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2693   if(mdim!=(int)cm.getDimension())
2694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2695   const int *ptI=_nodal_connec_index->getConstPointer();
2696   const int *pt=_nodal_connec->getConstPointer();
2697   for(int i=0;i<nbCells;i++)
2698     {
2699       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2700         ret->pushBackSilent(i);
2701     }
2702   return ret.retn();
2703 }
2704
2705 /*!
2706  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2707  */
2708 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2709 {
2710   const int *ptI=_nodal_connec_index->getConstPointer();
2711   const int *pt=_nodal_connec->getConstPointer();
2712   int nbOfCells=getNumberOfCells();
2713   int ret=0;
2714   for(int i=0;i<nbOfCells;i++)
2715     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2716       ret++;
2717   return ret;
2718 }
2719
2720 /*!
2721  * Returns the nodal connectivity of a given cell.
2722  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2723  * all returned node ids can be used in getCoordinatesOfNode().
2724  *  \param [in] cellId - an id of the cell of interest.
2725  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2726  *         cleared before the appending.
2727  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2728  */
2729 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2730 {
2731   const int *ptI=_nodal_connec_index->getConstPointer();
2732   const int *pt=_nodal_connec->getConstPointer();
2733   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2734     if(*w>=0)
2735       conn.push_back(*w);
2736 }
2737
2738 std::string MEDCouplingUMesh::simpleRepr() const
2739 {
2740   static const char msg0[]="No coordinates specified !";
2741   std::ostringstream ret;
2742   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2743   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2744   int tmpp1,tmpp2;
2745   double tt=getTime(tmpp1,tmpp2);
2746   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2747   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2748   if(_mesh_dim>=-1)
2749     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2750   else
2751     { ret << " Mesh dimension has not been set or is invalid !"; }
2752   if(_coords!=0)
2753     {
2754       const int spaceDim=getSpaceDimension();
2755       ret << spaceDim << "\nInfo attached on space dimension : ";
2756       for(int i=0;i<spaceDim;i++)
2757         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2758       ret << "\n";
2759     }
2760   else
2761     ret << msg0 << "\n";
2762   ret << "Number of nodes : ";
2763   if(_coords!=0)
2764     ret << getNumberOfNodes() << "\n";
2765   else
2766     ret << msg0 << "\n";
2767   ret << "Number of cells : ";
2768   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2769     ret << getNumberOfCells() << "\n";
2770   else
2771     ret << "No connectivity specified !" << "\n";
2772   ret << "Cell types present : ";
2773   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2774     {
2775       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2776       ret << cm.getRepr() << " ";
2777     }
2778   ret << "\n";
2779   return ret.str();
2780 }
2781
2782 std::string MEDCouplingUMesh::advancedRepr() const
2783 {
2784   std::ostringstream ret;
2785   ret << simpleRepr();
2786   ret << "\nCoordinates array : \n___________________\n\n";
2787   if(_coords)
2788     _coords->reprWithoutNameStream(ret);
2789   else
2790     ret << "No array set !\n";
2791   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2792   reprConnectivityOfThisLL(ret);
2793   return ret.str();
2794 }
2795
2796 /*!
2797  * This method returns a C++ code that is a dump of \a this.
2798  * This method will throw if this is not fully defined.
2799  */
2800 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2801 {
2802   static const char coordsName[]="coords";
2803   static const char connName[]="conn";
2804   static const char connIName[]="connI";
2805   checkFullyDefined();
2806   std::ostringstream ret; ret << "// coordinates" << std::endl;
2807   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2808   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2809   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2810   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2811   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2812   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2813   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2814   return ret.str();
2815 }
2816
2817 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2818 {
2819   std::ostringstream ret;
2820   reprConnectivityOfThisLL(ret);
2821   return ret.str();
2822 }
2823
2824 /*!
2825  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2826  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2827  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2828  * some algos).
2829  * 
2830  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2831  * 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
2832  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2833  */
2834 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2835 {
2836   int mdim=getMeshDimension();
2837   if(mdim<0)
2838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2839   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2841   bool needToCpyCT=true;
2842   if(!_nodal_connec)
2843     {
2844       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2845       needToCpyCT=false;
2846     }
2847   else
2848     {
2849       tmp1=_nodal_connec;
2850       tmp1->incrRef();
2851     }
2852   if(!_nodal_connec_index)
2853     {
2854       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2855       needToCpyCT=false;
2856     }
2857   else
2858     {
2859       tmp2=_nodal_connec_index;
2860       tmp2->incrRef();
2861     }
2862   ret->setConnectivity(tmp1,tmp2,false);
2863   if(needToCpyCT)
2864     ret->_types=_types;
2865   if(!_coords)
2866     {
2867       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2868       ret->setCoords(coords);
2869     }
2870   else
2871     ret->setCoords(_coords);
2872   return ret.retn();
2873 }
2874
2875 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2876 {
2877   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2878     {
2879       int nbOfCells=getNumberOfCells();
2880       const int *c=_nodal_connec->getConstPointer();
2881       const int *ci=_nodal_connec_index->getConstPointer();
2882       for(int i=0;i<nbOfCells;i++)
2883         {
2884           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2885           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2886           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2887           stream << "\n";
2888         }
2889     }
2890   else
2891     stream << "Connectivity not defined !\n";
2892 }
2893
2894 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2895 {
2896   const int *ptI=_nodal_connec_index->getConstPointer();
2897   const int *pt=_nodal_connec->getConstPointer();
2898   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2899     return ptI[cellId+1]-ptI[cellId]-1;
2900   else
2901     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2902 }
2903
2904 /*!
2905  * Returns types of cells of the specified part of \a this mesh.
2906  * This method avoids computing sub-mesh explicitely to get its types.
2907  *  \param [in] begin - an array of cell ids of interest.
2908  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2909  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2910  *         describing the cell types. 
2911  *  \throw If the coordinates array is not set.
2912  *  \throw If the nodal connectivity of cells is not defined.
2913  *  \sa getAllTypes()
2914  */
2915 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2916 {
2917   checkFullyDefined();
2918   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2919   const int *conn=_nodal_connec->getConstPointer();
2920   const int *connIndex=_nodal_connec_index->getConstPointer();
2921   for(const int *w=begin;w!=end;w++)
2922     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2923   return ret;
2924 }
2925
2926 /*!
2927  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2928  * a set of types of cells constituting \a this mesh. 
2929  * This method is for advanced users having prepared their connectivity before. For
2930  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2931  *  \param [in] conn - the nodal connectivity array. 
2932  *  \param [in] connIndex - the nodal connectivity index array.
2933  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2934  *         mesh is updated.
2935  */
2936 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2937 {
2938   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2939   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2940   if(isComputingTypes)
2941     computeTypes();
2942   declareAsNew();
2943 }
2944
2945 /*!
2946  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2947  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2948  */
2949 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2950                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2951                                                                                 _types(other._types)
2952 {
2953   if(other._nodal_connec)
2954     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2955   if(other._nodal_connec_index)
2956     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2957 }
2958
2959 MEDCouplingUMesh::~MEDCouplingUMesh()
2960 {
2961   if(_nodal_connec)
2962     _nodal_connec->decrRef();
2963   if(_nodal_connec_index)
2964     _nodal_connec_index->decrRef();
2965 }
2966
2967 /*!
2968  * Recomputes a set of cell types of \a this mesh. For more info see
2969  * \ref MEDCouplingUMeshNodalConnectivity.
2970  */
2971 void MEDCouplingUMesh::computeTypes()
2972 {
2973   if(_nodal_connec && _nodal_connec_index)
2974     {
2975       _types.clear();
2976       const int *conn=_nodal_connec->getConstPointer();
2977       const int *connIndex=_nodal_connec_index->getConstPointer();
2978       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2979       if (nbOfElem > 0)
2980         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2981           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2982     }
2983 }
2984
2985 /*!
2986  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2987  */
2988 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2989 {
2990   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2991     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2992 }
2993
2994 /*!
2995  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2996  */
2997 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2998 {
2999   if(!_nodal_connec_index || !_nodal_connec)
3000     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3001 }
3002
3003 /*!
3004  * Returns a number of cells constituting \a this mesh. 
3005  *  \return int - the number of cells in \a this mesh.
3006  *  \throw If the nodal connectivity of cells is not defined.
3007  */
3008 int MEDCouplingUMesh::getNumberOfCells() const
3009
3010   if(_nodal_connec_index)
3011     return _nodal_connec_index->getNumberOfTuples()-1;
3012   else
3013     if(_mesh_dim==-1)
3014       return 1;
3015     else
3016       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3017 }
3018
3019 /*!
3020  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3021  * mesh. For more info see \ref MEDCouplingMeshesPage.
3022  *  \return int - the dimension of \a this mesh.
3023  *  \throw If the mesh dimension is not defined using setMeshDimension().
3024  */
3025 int MEDCouplingUMesh::getMeshDimension() const
3026 {
3027   if(_mesh_dim<-1)
3028     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3029   return _mesh_dim;
3030 }
3031
3032 /*!
3033  * Returns a length of the nodal connectivity array.
3034  * This method is for test reason. Normally the integer returned is not useable by
3035  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3036  *  \return int - the length of the nodal connectivity array.
3037  */
3038 int MEDCouplingUMesh::getMeshLength() const
3039 {
3040   return _nodal_connec->getNbOfElems();
3041 }
3042
3043 /*!
3044  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3045  */
3046 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3047 {
3048   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3049   tinyInfo.push_back(getMeshDimension());
3050   tinyInfo.push_back(getNumberOfCells());
3051   if(_nodal_connec)
3052     tinyInfo.push_back(getMeshLength());
3053   else
3054     tinyInfo.push_back(-1);
3055 }
3056
3057 /*!
3058  * First step of unserialization process.
3059  */
3060 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3061 {
3062   return tinyInfo[6]<=0;
3063 }
3064
3065 /*!
3066  * Second step of serialization process.
3067  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3068  */
3069 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3070 {
3071   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3072   if(tinyInfo[5]!=-1)
3073     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3074 }
3075
3076 /*!
3077  * Third and final step of serialization process.
3078  */
3079 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3080 {
3081   MEDCouplingPointSet::serialize(a1,a2);
3082   if(getMeshDimension()>-1)
3083     {
3084       a1=DataArrayInt::New();
3085       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3086       int *ptA1=a1->getPointer();
3087       const int *conn=getNodalConnectivity()->getConstPointer();
3088       const int *index=getNodalConnectivityIndex()->getConstPointer();
3089       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3090       std::copy(conn,conn+getMeshLength(),ptA1);
3091     }
3092   else
3093     a1=0;
3094 }
3095
3096 /*!
3097  * Second and final unserialization process.
3098  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3099  */
3100 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3101 {
3102   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3103   setMeshDimension(tinyInfo[5]);
3104   if(tinyInfo[7]!=-1)
3105     {
3106       // Connectivity
3107       const int *recvBuffer=a1->getConstPointer();
3108       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3109       myConnecIndex->alloc(tinyInfo[6]+1,1);
3110       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3112       myConnec->alloc(tinyInfo[7],1);
3113       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3114       setConnectivity(myConnec, myConnecIndex);
3115     }
3116 }
3117
3118 /*!
3119  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3120  * CellIds are given using range specified by a start an end and step.
3121  */
3122 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3123 {
3124   checkFullyDefined();
3125   int ncell=getNumberOfCells();
3126   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3127   ret->_mesh_dim=_mesh_dim;
3128   ret->setCoords(_coords);
3129   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3131   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3132   int work=start;
3133   const int *conn=_nodal_connec->getConstPointer();
3134   const int *connIndex=_nodal_connec_index->getConstPointer();
3135   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3136     {
3137       if(work>=0 && work<ncell)
3138         {
3139           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3140         }
3141       else
3142         {
3143           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3144           throw INTERP_KERNEL::Exception(oss.str().c_str());
3145         }
3146     }
3147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3148   int *newConnPtr=newConn->getPointer();
3149   std::set<INTERP_KERNEL::NormalizedCellType> types;
3150   work=start;
3151   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3152     {
3153       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3154       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3155     }
3156   ret->setConnectivity(newConn,newConnI,false);
3157   ret->_types=types;
3158   ret->copyTinyInfoFrom(this);
3159   return ret.retn();
3160 }
3161
3162 /*!
3163  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3164  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3165  * The return newly allocated mesh will share the same coordinates as \a this.
3166  */
3167 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3168 {
3169   checkFullyDefined();
3170   int ncell=getNumberOfCells();
3171   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3172   ret->_mesh_dim=_mesh_dim;
3173   ret->setCoords(_coords);
3174   std::size_t nbOfElemsRet=std::distance(begin,end);
3175   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3176   connIndexRet[0]=0;
3177   const int *conn=_nodal_connec->getConstPointer();
3178   const int *connIndex=_nodal_connec_index->getConstPointer();
3179   int newNbring=0;
3180   for(const int *work=begin;work!=end;work++,newNbring++)
3181     {
3182       if(*work>=0 && *work<ncell)
3183         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3184       else
3185         {
3186           free(connIndexRet);
3187           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3188           throw INTERP_KERNEL::Exception(oss.str().c_str());
3189         }
3190     }
3191   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3192   int *connRetWork=connRet;
3193   std::set<INTERP_KERNEL::NormalizedCellType> types;
3194   for(const int *work=begin;work!=end;work++)
3195     {
3196       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3197       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3198     }
3199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3200   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3202   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3203   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3204   ret->_types=types;
3205   ret->copyTinyInfoFrom(this);
3206   return ret.retn();
3207 }
3208
3209 /*!
3210  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3211  * mesh.<br>
3212  * For 1D cells, the returned field contains lengths.<br>
3213  * For 2D cells, the returned field contains areas.<br>
3214  * For 3D cells, the returned field contains volumes.
3215  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3216  *         orientation, i.e. the volume is always positive.
3217  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3218  *         and one time . The caller is to delete this field using decrRef() as it is no
3219  *         more needed.
3220  */
3221 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3222 {
3223   std::string name="MeasureOfMesh_";
3224   name+=getName();
3225   int nbelem=getNumberOfCells();
3226   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3227   field->setName(name.c_str());
3228   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3229   array->alloc(nbelem,1);
3230   double *area_vol=array->getPointer();
3231   field->setArray(array) ; array=0;
3232   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3233   field->synchronizeTimeWithMesh();
3234   if(getMeshDimension()!=-1)
3235     {
3236       int ipt;
3237       INTERP_KERNEL::NormalizedCellType type;
3238       int dim_space=getSpaceDimension();
3239       const double *coords=getCoords()->getConstPointer();
3240       const int *connec=getNodalConnectivity()->getConstPointer();
3241       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3242       for(int iel=0;iel<nbelem;iel++)
3243         {
3244           ipt=connec_index[iel];
3245           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3246           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);
3247         }
3248       if(isAbs)
3249         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3250     }
3251   else
3252     {
3253       area_vol[0]=std::numeric_limits<double>::max();
3254     }
3255   return field.retn();
3256 }
3257
3258 /*!
3259  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3260  * mesh.<br>
3261  * For 1D cells, the returned array contains lengths.<br>
3262  * For 2D cells, the returned array contains areas.<br>
3263  * For 3D cells, the returned array contains volumes.
3264  * This method avoids building explicitly a part of \a this mesh to perform the work.
3265  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3266  *         orientation, i.e. the volume is always positive.
3267  *  \param [in] begin - an array of cell ids of interest.
3268  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3269  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3270  *          delete this array using decrRef() as it is no more needed.
3271  * 
3272  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3273  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3274  *  \sa getMeasureField()
3275  */
3276 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3277 {
3278   std::string name="PartMeasureOfMesh_";
3279   name+=getName();
3280   int nbelem=(int)std::distance(begin,end);
3281   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3282   array->setName(name.c_str());
3283   array->alloc(nbelem,1);
3284   double *area_vol=array->getPointer();
3285   if(getMeshDimension()!=-1)
3286     {
3287       int ipt;
3288       INTERP_KERNEL::NormalizedCellType type;
3289       int dim_space=getSpaceDimension();
3290       const double *coords=getCoords()->getConstPointer();
3291       const int *connec=getNodalConnectivity()->getConstPointer();
3292       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3293       for(const int *iel=begin;iel!=end;iel++)
3294         {
3295           ipt=connec_index[*iel];
3296           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3297           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3298         }
3299       if(isAbs)
3300         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3301     }
3302   else
3303     {
3304       area_vol[0]=std::numeric_limits<double>::max();
3305     }
3306   return array.retn();
3307 }
3308
3309 /*!
3310  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3311  * \a this one. The returned field contains the dual cell volume for each corresponding
3312  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3313  *  the dual mesh in P1 sens of \a this.<br>
3314  * For 1D cells, the returned field contains lengths.<br>
3315  * For 2D cells, the returned field contains areas.<br>
3316  * For 3D cells, the returned field contains volumes.
3317  * This method is useful to check "P1*" conservative interpolators.
3318  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3319  *         orientation, i.e. the volume is always positive.
3320  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3321  *          nodes and one time. The caller is to delete this array using decrRef() as
3322  *          it is no more needed.
3323  */
3324 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3325 {
3326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3327   std::string name="MeasureOnNodeOfMesh_";
3328   name+=getName();
3329   int nbNodes=getNumberOfNodes();
3330   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3331   double cst=1./((double)getMeshDimension()+1.);
3332   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3333   array->alloc(nbNodes,1);
3334   double *valsToFill=array->getPointer();
3335   std::fill(valsToFill,valsToFill+nbNodes,0.);
3336   const double *values=tmp->getArray()->getConstPointer();
3337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3339   getReverseNodalConnectivity(da,daInd);
3340   const int *daPtr=da->getConstPointer();
3341   const int *daIPtr=daInd->getConstPointer();
3342   for(int i=0;i<nbNodes;i++)
3343     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3344       valsToFill[i]+=cst*values[*cell];
3345   ret->setMesh(this);
3346   ret->setArray(array);
3347   return ret.retn();
3348 }
3349
3350 /*!
3351  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3352  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3353  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3354  * and are normalized.
3355  * <br> \a this can be either 
3356  * - a  2D mesh in 2D or 3D space or 
3357  * - an 1D mesh in 2D space.
3358  * 
3359  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3360  *          cells and one time. The caller is to delete this field using decrRef() as
3361  *          it is no more needed.
3362  *  \throw If the nodal connectivity of cells is not defined.
3363  *  \throw If the coordinates array is not set.
3364  *  \throw If the mesh dimension is not set.
3365  *  \throw If the mesh and space dimension is not as specified above.
3366  */
3367 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3368 {
3369   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3370     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3371   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3373   int nbOfCells=getNumberOfCells();
3374   int nbComp=getMeshDimension()+1;
3375   array->alloc(nbOfCells,nbComp);
3376   double *vals=array->getPointer();
3377   const int *connI=_nodal_connec_index->getConstPointer();
3378   const int *conn=_nodal_connec->getConstPointer();
3379   const double *coords=_coords->getConstPointer();
3380   if(getMeshDimension()==2)
3381     {
3382       if(getSpaceDimension()==3)
3383         {
3384           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3385           const double *locPtr=loc->getConstPointer();
3386           for(int i=0;i<nbOfCells;i++,vals+=3)
3387             {
3388               int offset=connI[i];
3389               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3390               double n=INTERP_KERNEL::norm<3>(vals);
3391               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3392             }
3393         }
3394       else
3395         {
3396           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3397           const double *isAbsPtr=isAbs->getArray()->begin();
3398           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3399             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3400         }
3401     }
3402   else//meshdimension==1
3403     {
3404       double tmp[2];
3405       for(int i=0;i<nbOfCells;i++)
3406         {
3407           int offset=connI[i];
3408           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3409           double n=INTERP_KERNEL::norm<2>(tmp);
3410           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3411           *vals++=-tmp[1];
3412           *vals++=tmp[0];
3413         }
3414     }
3415   ret->setArray(array);
3416   ret->setMesh(this);
3417   ret->synchronizeTimeWithSupport();
3418   return ret.retn();
3419 }
3420
3421 /*!
3422  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3423  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3424  * and are normalized.
3425  * <br> \a this can be either 
3426  * - a  2D mesh in 2D or 3D space or 
3427  * - an 1D mesh in 2D space.
3428  * 
3429  * This method avoids building explicitly a part of \a this mesh to perform the work.
3430  *  \param [in] begin - an array of cell ids of interest.
3431  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3432  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3433  *          cells and one time. The caller is to delete this field using decrRef() as
3434  *          it is no more needed.
3435  *  \throw If the nodal connectivity of cells is not defined.
3436  *  \throw If the coordinates array is not set.
3437  *  \throw If the mesh dimension is not set.
3438  *  \throw If the mesh and space dimension is not as specified above.
3439  *  \sa buildOrthogonalField()
3440  *
3441  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3442  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3443  */
3444 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3445 {
3446   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3447     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3448   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3449   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3450   std::size_t nbelems=std::distance(begin,end);
3451   int nbComp=getMeshDimension()+1;
3452   array->alloc((int)nbelems,nbComp);
3453   double *vals=array->getPointer();
3454   const int *connI=_nodal_connec_index->getConstPointer();
3455   const int *conn=_nodal_connec->getConstPointer();
3456   const double *coords=_coords->getConstPointer();
3457   if(getMeshDimension()==2)
3458     {
3459       if(getSpaceDimension()==3)
3460         {
3461           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3462           const double *locPtr=loc->getConstPointer();
3463           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3464             {
3465               int offset=connI[*i];
3466               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3467               double n=INTERP_KERNEL::norm<3>(vals);
3468               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3469             }
3470         }
3471       else
3472         {
3473           for(std::size_t i=0;i<nbelems;i++)
3474             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3475         }
3476     }
3477   else//meshdimension==1
3478     {
3479       double tmp[2];
3480       for(const int *i=begin;i!=end;i++)
3481         {
3482           int offset=connI[*i];
3483           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3484           double n=INTERP_KERNEL::norm<2>(tmp);
3485           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3486           *vals++=-tmp[1];
3487           *vals++=tmp[0];
3488         }
3489     }
3490   ret->setArray(array);
3491   ret->setMesh(this);
3492   ret->synchronizeTimeWithSupport();
3493   return ret.retn();
3494 }
3495
3496 /*!
3497  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3498  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3499  * and are \b not normalized.
3500  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3501  *          cells and one time. The caller is to delete this field using decrRef() as
3502  *          it is no more needed.
3503  *  \throw If the nodal connectivity of cells is not defined.
3504  *  \throw If the coordinates array is not set.
3505  *  \throw If \a this->getMeshDimension() != 1.
3506  *  \throw If \a this mesh includes cells of type other than SEG2.
3507  */
3508 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3509 {
3510    if(getMeshDimension()!=1)
3511     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3512    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3513      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3514    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3515    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3516    int nbOfCells=getNumberOfCells();
3517    int spaceDim=getSpaceDimension();
3518    array->alloc(nbOfCells,spaceDim);
3519    double *pt=array->getPointer();
3520    const double *coo=getCoords()->getConstPointer();
3521    std::vector<int> conn;
3522    conn.reserve(2);
3523    for(int i=0;i<nbOfCells;i++)
3524      {
3525        conn.resize(0);
3526        getNodeIdsOfCell(i,conn);
3527        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3528      }
3529    ret->setArray(array);
3530    ret->setMesh(this);
3531    ret->synchronizeTimeWithSupport();
3532    return ret.retn();   
3533 }
3534
3535 /*!
3536  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3537  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3538  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3539  * from. If a result face is shared by two 3D cells, then the face in included twice in
3540  * the result mesh.
3541  *  \param [in] origin - 3 components of a point defining location of the plane.
3542  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3543  *         must be greater than 1e-6.
3544  *  \param [in] eps - half-thickness of the plane.
3545  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3546  *         producing correspondent 2D cells. The caller is to delete this array
3547  *         using decrRef() as it is no more needed.
3548  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3549  *         not share the node coordinates array with \a this mesh. The caller is to
3550  *         delete this mesh using decrRef() as it is no more needed.  
3551  *  \throw If the coordinates array is not set.
3552  *  \throw If the nodal connectivity of cells is not defined.
3553  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3554  *  \throw If magnitude of \a vec is less than 1e-6.
3555  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3556  *  \throw If \a this includes quadratic cells.
3557  */
3558 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3559 {
3560   checkFullyDefined();
3561   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3564   if(candidates->empty())
3565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3566   std::vector<int> nodes;
3567   DataArrayInt *cellIds1D=0;
3568   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3569   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3571   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3572   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3573   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3574   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3575   revDesc2=0; revDescIndx2=0;
3576   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3577   revDesc1=0; revDescIndx1=0;
3578   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3580   //
3581   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3582   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3583     cut3DCurve[*it]=-1;
3584   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3585   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3586   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3587                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3588                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3590   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3591   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3592   if(cellIds2->empty())
3593     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3594   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3595   ret->setCoords(mDesc1->getCoords());
3596   ret->setConnectivity(conn,connI,true);
3597   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3598   return ret.retn();
3599 }
3600
3601 /*!
3602  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3603 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
3604 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3605 the result mesh.
3606  *  \param [in] origin - 3 components of a point defining location of the plane.
3607  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3608  *         must be greater than 1e-6.
3609  *  \param [in] eps - half-thickness of the plane.
3610  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3611  *         producing correspondent segments. The caller is to delete this array
3612  *         using decrRef() as it is no more needed.
3613  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3614  *         mesh in 3D space. This mesh does not share the node coordinates array with
3615  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3616  *         no more needed. 
3617  *  \throw If the coordinates array is not set.
3618  *  \throw If the nodal connectivity of cells is not defined.
3619  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3620  *  \throw If magnitude of \a vec is less than 1e-6.
3621  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3622  *  \throw If \a this includes quadratic cells.
3623  */
3624 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3625 {
3626   checkFullyDefined();
3627   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3628     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3630   if(candidates->empty())
3631     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3632   std::vector<int> nodes;
3633   DataArrayInt *cellIds1D=0;
3634   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3635   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3637   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3640   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3641   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3643   //
3644   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3645   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3646     cut3DCurve[*it]=-1;
3647   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3648   int ncellsSub=subMesh->getNumberOfCells();
3649   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3650   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3651                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3652                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3654   conn->alloc(0,1);
3655   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3656   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3657   for(int i=0;i<ncellsSub;i++)
3658     {
3659       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3660         {
3661           if(cut3DSurf[i].first!=-2)
3662             {
3663               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3664               connI->pushBackSilent(conn->getNumberOfTuples());
3665               cellIds2->pushBackSilent(i);
3666             }
3667           else
3668             {
3669               int cellId3DSurf=cut3DSurf[i].second;
3670               int offset=nodalI[cellId3DSurf]+1;
3671               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3672               for(int j=0;j<nbOfEdges;j++)
3673                 {
3674                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3675                   connI->pushBackSilent(conn->getNumberOfTuples());
3676                   cellIds2->pushBackSilent(cellId3DSurf);
3677                 }
3678             }
3679         }
3680     }
3681   if(cellIds2->empty())
3682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3683   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3684   ret->setCoords(mDesc1->getCoords());
3685   ret->setConnectivity(conn,connI,true);
3686   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3687   return ret.retn();
3688 }
3689
3690 /*!
3691  * Finds cells whose bounding boxes intersect a given plane.
3692  *  \param [in] origin - 3 components of a point defining location of the plane.
3693  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3694  *         must be greater than 1e-6.
3695  *  \param [in] eps - half-thickness of the plane.
3696  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3697  *         cells. The caller is to delete this array using decrRef() as it is no more
3698  *         needed.
3699  *  \throw If the coordinates array is not set.
3700  *  \throw If the nodal connectivity of cells is not defined.
3701  *  \throw If \a this->getSpaceDimension() != 3.
3702  *  \throw If magnitude of \a vec is less than 1e-6.
3703  *  \sa buildSlice3D()
3704  */
3705 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3706 {
3707   checkFullyDefined();
3708   if(getSpaceDimension()!=3)
3709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3710   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3711   if(normm<1e-6)
3712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3713   double vec2[3];
3714   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3715   double angle=acos(vec[2]/normm);
3716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3717   double bbox[6];
3718   if(angle>eps)
3719     {
3720       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3721       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3722       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3723       mw->setCoords(coo);
3724       mw->getBoundingBox(bbox);
3725       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3726       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3727     }
3728   else
3729     {
3730       getBoundingBox(bbox);
3731       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3732       cellIds=getCellsInBoundingBox(bbox,eps);
3733     }
3734   return cellIds.retn();
3735 }
3736
3737 /*!
3738  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3739  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3740  * No consideration of coordinate is done by this method.
3741  * 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)
3742  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3743  */
3744 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3745 {
3746   if(getMeshDimension()!=1)
3747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3748   int nbCells=getNumberOfCells();
3749   if(nbCells<1)
3750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3751   const int *connI=_nodal_connec_index->getConstPointer();
3752   const int *conn=_nodal_connec->getConstPointer();
3753   int ref=conn[connI[0]+2];
3754   for(int i=1;i<nbCells;i++)
3755     {
3756       if(conn[connI[i]+1]!=ref)
3757         return false;
3758       ref=conn[connI[i]+2];
3759     }
3760   return true;
3761 }
3762
3763 /*!
3764  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3765  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3766  * \param pt reference point of the line
3767  * \param v normalized director vector of the line
3768  * \param eps max precision before throwing an exception
3769  * \param res output of size this->getNumberOfCells
3770  */
3771 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3772 {
3773   if(getMeshDimension()!=1)
3774     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3775    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3776      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3777    if(getSpaceDimension()!=3)
3778      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3779    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3780    const double *fPtr=f->getArray()->getConstPointer();
3781    double tmp[3];
3782    for(int i=0;i<getNumberOfCells();i++)
3783      {
3784        const double *tmp1=fPtr+3*i;
3785        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3786        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3787        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3788        double n1=INTERP_KERNEL::norm<3>(tmp);
3789        n1/=INTERP_KERNEL::norm<3>(tmp1);
3790        if(n1>eps)
3791          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3792      }
3793    const double *coo=getCoords()->getConstPointer();
3794    for(int i=0;i<getNumberOfNodes();i++)
3795      {
3796        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3797        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3798        res[i]=std::accumulate(tmp,tmp+3,0.);
3799      }
3800 }
3801
3802 /*!
3803  * 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. 
3804  * \a this is expected to be a mesh so that its space dimension is equal to its
3805  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3806  * 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).
3807  
3808  * 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
3809  * 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).
3810  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3811  *
3812  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3813  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3814  *
3815  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3816  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3817  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3818  * \return the positive value of the distance.
3819  * \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
3820  * dimension - 1.
3821  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3822  */
3823 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3824 {
3825   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3826   if(meshDim!=spaceDim-1)
3827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3828   if(meshDim!=2 && meshDim!=1)
3829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3830   checkFullyDefined();
3831   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3832     { 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()); }
3833   DataArrayInt *ret1=0;
3834   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3835   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3837   cellId=*ret1Safe->begin();
3838   return *ret0->begin();
3839 }
3840
3841 /*!
3842  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3843  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3844  * 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
3845  * 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).
3846  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3847  * 
3848  * \a this is expected to be a mesh so that its space dimension is equal to its
3849  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3850  * 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).
3851  *
3852  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3853  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3854  *
3855  * \param [in] pts the list of points in which each tuple represents a point
3856  * \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.
3857  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3858  * \throw if number of components of \a pts is not equal to the space dimension.
3859  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3860  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3861  */
3862 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3863 {
3864   if(!pts)
3865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3866   pts->checkAllocated();
3867   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3868   if(meshDim!=spaceDim-1)
3869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3870   if(meshDim!=2 && meshDim!=1)
3871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3872   if(pts->getNumberOfComponents()!=spaceDim)
3873     {
3874       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3875       throw INTERP_KERNEL::Exception(oss.str().c_str());
3876     }
3877   checkFullyDefined();
3878   int nbCells=getNumberOfCells();
3879   if(nbCells==0)
3880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3881   int nbOfPts=pts->getNumberOfTuples();
3882   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3884   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3885   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3886   std::vector<double> bbox;
3887   getBoundingBoxForBBTree(bbox);
3888   switch(spaceDim)
3889     {
3890     case 3:
3891       {
3892         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3893         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3894           {
3895             double x=std::numeric_limits<double>::max();
3896             std::vector<int> elems;
3897             myTree.getMinDistanceOfMax(ptsPtr,x);
3898             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3899             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3900           }
3901         break;
3902       }
3903     case 2:
3904       {
3905         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3906         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3907           {
3908             double x=std::numeric_limits<double>::max();
3909             std::vector<int> elems;
3910             myTree.getMinDistanceOfMax(ptsPtr,x);
3911             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3912             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3913           }
3914         break;
3915       }
3916     default:
3917       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3918     }
3919   cellIds=ret1.retn();
3920   return ret0.retn();
3921 }
3922
3923 /*!
3924  * \param [in] pt the start pointer (included) of the coordinates of the point
3925  * \param [in] cellIdsBg the start pointer (included) of cellIds
3926  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3927  * \param [in] nc nodal connectivity
3928  * \param [in] ncI nodal connectivity index
3929  * \param [in,out] ret0 the min distance between \a this and the external input point
3930  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3931  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3932  */
3933 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) throw(INTERP_KERNEL::Exception)
3934 {
3935   cellId=-1;
3936   ret0=std::numeric_limits<double>::max();
3937   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3938     {
3939       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3940         {
3941         case INTERP_KERNEL::NORM_TRI3:
3942           {
3943             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3944             if(tmp<ret0)
3945               { ret0=tmp; cellId=*zeCell; }
3946             break;
3947           }
3948         case INTERP_KERNEL::NORM_QUAD4:
3949         case INTERP_KERNEL::NORM_POLYGON:
3950           {
3951             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3952             if(tmp<ret0)
3953               { ret0=tmp; cellId=*zeCell; }
3954             break;
3955           }
3956         default:
3957           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3958         }
3959     }
3960 }
3961
3962 /*!
3963  * \param [in] pt the start pointer (included) of the coordinates of the point
3964  * \param [in] cellIdsBg the start pointer (included) of cellIds
3965  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3966  * \param [in] nc nodal connectivity
3967  * \param [in] ncI nodal connectivity index
3968  * \param [in,out] ret0 the min distance between \a this and the external input point
3969  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3970  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3971  */
3972 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) throw(INTERP_KERNEL::Exception)
3973 {
3974   cellId=-1;
3975   ret0=std::numeric_limits<double>::max();
3976   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3977     {
3978        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3979         {
3980         case INTERP_KERNEL::NORM_SEG2:
3981           {
3982             std::size_t uselessEntry=0;
3983             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3984             tmp=sqrt(tmp);
3985             if(tmp<ret0)
3986               { ret0=tmp; cellId=*zeCell; }
3987             break;
3988           }
3989         default:
3990           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3991         }
3992     }
3993 }
3994
3995 /*!
3996  * Finds cells in contact with a ball (i.e. a point with precision). 
3997  * \warning This method is suitable if the caller intends to evaluate only one
3998  *          point, for more points getCellsContainingPoints() is recommended as it is
3999  *          faster. 
4000  *  \param [in] pos - array of coordinates of the ball central point.
4001  *  \param [in] eps - ball radius.
4002  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4003  *         if there are no such cells.
4004  *  \throw If the coordinates array is not set.
4005  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4006  */
4007 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4008 {
4009   std::vector<int> elts;
4010   getCellsContainingPoint(pos,eps,elts);
4011   if(elts.empty())
4012     return -1;
4013   return elts.front();
4014 }
4015
4016 /*!
4017  * Finds cells in contact with a ball (i.e. a point with precision).
4018  * \warning This method is suitable if the caller intends to evaluate only one
4019  *          point, for more points getCellsContainingPoints() is recommended as it is
4020  *          faster. 
4021  *  \param [in] pos - array of coordinates of the ball central point.
4022  *  \param [in] eps - ball radius.
4023  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4024  *         before inserting ids.
4025  *  \throw If the coordinates array is not set.
4026  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4027  *
4028  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4029  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4030  */
4031 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4032 {
4033   std::vector<int> eltsIndex;
4034   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4035 }
4036
4037 /// @cond INTERNAL
4038
4039 namespace ParaMEDMEM
4040 {
4041   template<const int SPACEDIMM>
4042   class DummyClsMCUG
4043   {
4044   public:
4045     static const int MY_SPACEDIM=SPACEDIMM;
4046     static const int MY_MESHDIM=8;
4047     typedef int MyConnType;
4048     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4049     // begin
4050     // useless, but for windows compilation ...
4051     const double* getCoordinatesPtr() const { return 0; }
4052     const int* getConnectivityPtr() const { return 0; }
4053     const int* getConnectivityIndexPtr() const { return 0; }
4054     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4055     // end
4056   };
4057
4058   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4059   {
4060     INTERP_KERNEL::Edge *ret=0;
4061     switch(typ)
4062       {
4063       case INTERP_KERNEL::NORM_SEG2:
4064         {
4065           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4066           break;
4067         }
4068       case INTERP_KERNEL::NORM_SEG3:
4069         {
4070           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4071           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4072           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4073           bool colinearity=inters.areColinears();
4074           delete e1; delete e2;
4075           if(colinearity)
4076             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4077           else
4078             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4079           mapp2[bg[2]].second=false;
4080           break;
4081         }
4082       default:
4083         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4084       }
4085     return ret;
4086   }
4087
4088   /*!
4089    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4090    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4091    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4092    */
4093   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4094   {
4095     mapp.clear();
4096     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.
4097     const double *coo=mDesc->getCoords()->getConstPointer();
4098     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4099     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4100     std::set<int> s;
4101     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4102       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4103     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4104       {
4105         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4106         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4107       }
4108     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4109     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4110       {
4111         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4112         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4113       }
4114     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4115       {
4116         if((*it2).second.second)
4117           mapp[(*it2).second.first]=(*it2).first;
4118         ((*it2).second.first)->decrRef();
4119       }
4120     return ret;
4121   }
4122
4123   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4124   {
4125     if(nodeId>=offset2)
4126       {
4127         int locId=nodeId-offset2;
4128         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4129       }
4130     if(nodeId>=offset1)
4131       {
4132         int locId=nodeId-offset1;
4133         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4134       }
4135     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4136   }
4137
4138   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4139                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4140                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4141   {
4142     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4143       {
4144         int eltId1=abs(*desc1)-1;
4145         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4146           {
4147             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4148             if(it==mappRev.end())
4149               {
4150                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4151                 mapp[node]=*it1;
4152                 mappRev[*it1]=node;
4153               }
4154           }
4155       }
4156   }
4157 }
4158
4159 /// @endcond
4160
4161 template<int SPACEDIM>
4162 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4163                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4164 {
4165   std::vector<double> bbox;
4166   eltsIndex.resize(nbOfPoints+1);
4167   eltsIndex[0]=0;
4168   elts.clear();
4169   getBoundingBoxForBBTree(bbox);
4170   int nbOfCells=getNumberOfCells();
4171   const int *conn=_nodal_connec->getConstPointer();
4172   const int *connI=_nodal_connec_index->getConstPointer();
4173   double bb[2*SPACEDIM];
4174   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4175   for(int i=0;i<nbOfPoints;i++)
4176     {
4177       eltsIndex[i+1]=eltsIndex[i];
4178       for(int j=0;j<SPACEDIM;j++)
4179         {
4180           bb[2*j]=pos[SPACEDIM*i+j];
4181           bb[2*j+1]=pos[SPACEDIM*i+j];
4182         }
4183       std::vector<int> candidates;
4184       myTree.getIntersectingElems(bb,candidates);
4185       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4186         {
4187           int sz=connI[(*iter)+1]-connI[*iter]-1;
4188           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4189                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4190                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4191             {
4192               eltsIndex[i+1]++;
4193               elts.push_back(*iter);
4194             }
4195         }
4196     }
4197 }
4198 /*!
4199  * Finds cells in contact with several balls (i.e. points with precision).
4200  * This method is an extension of getCellContainingPoint() and
4201  * getCellsContainingPoint() for the case of multiple points.
4202  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4203  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4204  *         this->getSpaceDimension() * \a nbOfPoints 
4205  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4206  *  \param [in] eps - radius of balls (i.e. the precision).
4207  *  \param [in,out] elts - vector returning ids of found cells.
4208  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4209  *         dividing cell ids in \a elts into groups each referring to one
4210  *         point. Its every element (except the last one) is an index pointing to the
4211  *         first id of a group of cells. For example cells in contact with the *i*-th
4212  *         point are described by following range of indices:
4213  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4214  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4215  *         Number of cells in contact with the *i*-th point is
4216  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4217  *  \throw If the coordinates array is not set.
4218  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4219  *
4220  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4221  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4222  */
4223 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4224                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4225 {
4226   int spaceDim=getSpaceDimension();
4227   int mDim=getMeshDimension();
4228   if(spaceDim==3)
4229     {
4230       if(mDim==3)
4231         {
4232           const double *coords=_coords->getConstPointer();
4233           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4234         }
4235       /*else if(mDim==2)
4236         {
4237           
4238         }*/
4239       else
4240         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4241     }
4242   else if(spaceDim==2)
4243     {
4244       if(mDim==2)
4245         {
4246           const double *coords=_coords->getConstPointer();
4247           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4248         }
4249       else
4250         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4251     }
4252   else if(spaceDim==1)
4253     {
4254       if(mDim==1)
4255         {
4256           const double *coords=_coords->getConstPointer();
4257           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4258         }
4259       else
4260         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4261     }
4262   else
4263     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4264 }
4265
4266 /*!
4267  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4268  * least two its edges intersect each other anywhere except their extremities. An
4269  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4270  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4271  *         cleared before filling in.
4272  *  \param [in] eps - precision.
4273  *  \throw If \a this->getMeshDimension() != 2.
4274  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4275  */
4276 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4277 {
4278   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4279   if(getMeshDimension()!=2)
4280     throw INTERP_KERNEL::Exception(msg);
4281   int spaceDim=getSpaceDimension();
4282   if(spaceDim!=2 && spaceDim!=3)
4283     throw INTERP_KERNEL::Exception(msg);
4284   const int *conn=_nodal_connec->getConstPointer();
4285   const int *connI=_nodal_connec_index->getConstPointer();
4286   int nbOfCells=getNumberOfCells();
4287   std::vector<double> cell2DinS2;
4288   for(int i=0;i<nbOfCells;i++)
4289     {
4290       int offset=connI[i];
4291       int nbOfNodesForCell=connI[i+1]-offset-1;
4292       if(nbOfNodesForCell<=3)
4293         continue;
4294       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4295       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4296       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4297         cells.push_back(i);
4298       cell2DinS2.clear();
4299     }
4300 }
4301
4302 /*!
4303  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4304  *
4305  * 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.
4306  * 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.
4307  * 
4308  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4309  * This convex envelop is computed using Jarvis march algorithm.
4310  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4311  * 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)
4312  * 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.
4313  *
4314  * \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.
4315  */
4316 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4317 {
4318   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4320   checkFullyDefined();
4321   const double *coords=getCoords()->getConstPointer();
4322   int nbOfCells=getNumberOfCells();
4323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4324   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4326   int *workIndexOut=nodalConnecIndexOut->getPointer();
4327   *workIndexOut=0;
4328   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4329   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4330   std::set<INTERP_KERNEL::NormalizedCellType> types;
4331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4332   isChanged->alloc(0,1);
4333   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4334     {
4335       int pos=nodalConnecOut->getNumberOfTuples();
4336       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4337         isChanged->pushBackSilent(i);
4338       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4339       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4340     }
4341   if(isChanged->empty())
4342     return 0;
4343   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4344   _types=types;
4345   return isChanged.retn();
4346 }
4347
4348 /*!
4349  * This method is \b NOT const because it can modify \a this.
4350  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4351  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4352  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4353  * \b 1 for translation and rotation around point of 'mesh1D'.
4354  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4355  */
4356 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4357 {
4358   checkFullyDefined();
4359   mesh1D->checkFullyDefined();
4360   if(!mesh1D->isContiguous1D())
4361     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4362   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4363     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4364   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4365     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4366   if(mesh1D->getMeshDimension()!=1)
4367     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4368   bool isQuad=false;
4369   if(isPresenceOfQuadratic())
4370     {
4371       if(mesh1D->isFullyQuadratic())
4372         isQuad=true;
4373       else
4374         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4375     }
4376   zipCoords();
4377   int oldNbOfNodes=getNumberOfNodes();
4378   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4379   switch(policy)
4380     {
4381     case 0:
4382       {
4383         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4384         break;
4385       }
4386     case 1:
4387       {
4388         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4389         break;
4390       }
4391     default:
4392       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4393     }
4394   setCoords(newCoords);
4395   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4396   updateTime();
4397   return ret.retn();
4398 }
4399
4400 /*!
4401  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4402  * If it is not the case an exception will be thrown.
4403  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4404  * intersection of plane defined by ('origin','vec').
4405  * This method has one in/out parameter : 'cut3DCurve'.
4406  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4407  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4408  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4409  * This method will throw an exception if \a this contains a non linear segment.
4410  */
4411 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4412 {
4413   checkFullyDefined();
4414   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4416   int ncells=getNumberOfCells();
4417   int nnodes=getNumberOfNodes();
4418   double vec2[3],vec3[3],vec4[3];
4419   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4420   if(normm<1e-6)
4421     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4422   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4423   const int *conn=_nodal_connec->getConstPointer();
4424   const int *connI=_nodal_connec_index->getConstPointer();
4425   const double *coo=_coords->getConstPointer();
4426   std::vector<double> addCoo;
4427   for(int i=0;i<ncells;i++)
4428     {
4429       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4430         {
4431           if(cut3DCurve[i]==-2)
4432             {
4433               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4434               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];
4435               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4436               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4437               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4438                 {
4439                   const double *st2=coo+3*st;
4440                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4441                   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]));
4442                   if(pos>eps && pos<1-eps)
4443                     {
4444                       int nNode=((int)addCoo.size())/3;
4445                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4446                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4447                       cut3DCurve[i]=nnodes+nNode;
4448                     }
4449                 }
4450             }
4451         }
4452       else
4453         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4454     }
4455   if(!addCoo.empty())
4456     {
4457       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4458       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4459       coo2->alloc(newNbOfNodes,3);
4460       double *tmp=coo2->getPointer();
4461       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4462       std::copy(addCoo.begin(),addCoo.end(),tmp);
4463       DataArrayDouble::SetArrayIn(coo2,_coords);
4464     }
4465 }
4466
4467 /*!
4468  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4469  * \param mesh1D is the input 1D mesh used for translation computation.
4470  * \return newCoords new coords filled by this method. 
4471  */
4472 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4473 {
4474   int oldNbOfNodes=getNumberOfNodes();
4475   int nbOf1DCells=mesh1D->getNumberOfCells();
4476   int spaceDim=getSpaceDimension();
4477   DataArrayDouble *ret=DataArrayDouble::New();
4478   std::vector<bool> isQuads;
4479   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4480   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4481   double *retPtr=ret->getPointer();
4482   const double *coords=getCoords()->getConstPointer();
4483   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4484   std::vector<int> v;
4485   std::vector<double> c;
4486   double vec[3];
4487   v.reserve(3);
4488   c.reserve(6);
4489   for(int i=0;i<nbOf1DCells;i++)
4490     {
4491       v.resize(0);
4492       mesh1D->getNodeIdsOfCell(i,v);
4493       c.resize(0);
4494       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4495       mesh1D->getCoordinatesOfNode(v[0],c);
4496       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4497       for(int j=0;j<oldNbOfNodes;j++)
4498         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4499       if(isQuad)
4500         {
4501           c.resize(0);
4502           mesh1D->getCoordinatesOfNode(v[1],c);
4503           mesh1D->getCoordinatesOfNode(v[0],c);
4504           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4505           for(int j=0;j<oldNbOfNodes;j++)
4506             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4507         }
4508     }
4509   ret->copyStringInfoFrom(*getCoords());
4510   return ret;
4511 }
4512
4513 /*!
4514  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4515  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4516  * \return newCoords new coords filled by this method. 
4517  */
4518 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4519 {
4520   if(mesh1D->getSpaceDimension()==2)
4521     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4522   if(mesh1D->getSpaceDimension()==3)
4523     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4524   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4525 }
4526
4527 /*!
4528  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4529  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4530  * \return newCoords new coords filled by this method. 
4531  */
4532 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4533 {
4534   if(isQuad)
4535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4536   int oldNbOfNodes=getNumberOfNodes();
4537   int nbOf1DCells=mesh1D->getNumberOfCells();
4538   if(nbOf1DCells<2)
4539     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4540   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4541   int nbOfLevsInVec=nbOf1DCells+1;
4542   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4543   double *retPtr=ret->getPointer();
4544   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4545   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4546   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4547   tmp->setCoords(tmp2);
4548   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4549   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4550   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4551   for(int i=1;i<nbOfLevsInVec;i++)
4552     {
4553       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4554       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4555       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4556       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4557       tmp->translate(vec);
4558       double tmp3[2],radius,alpha,alpha0;
4559       const double *p0=i+1<nbOfLevsInVec?begin:third;
4560       const double *p1=i+1<nbOfLevsInVec?end:begin;
4561       const double *p2=i+1<nbOfLevsInVec?third:end;
4562       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4563       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]);
4564       double angle=acos(cosangle/(radius*radius));
4565       tmp->rotate(end,0,angle);
4566       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4567     }
4568   return ret.retn();
4569 }
4570
4571 /*!
4572  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4573  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4574  * \return newCoords new coords filled by this method. 
4575  */
4576 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4577 {
4578   if(isQuad)
4579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4580   int oldNbOfNodes=getNumberOfNodes();
4581   int nbOf1DCells=mesh1D->getNumberOfCells();
4582   if(nbOf1DCells<2)
4583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4584   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4585   int nbOfLevsInVec=nbOf1DCells+1;
4586   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4587   double *retPtr=ret->getPointer();
4588   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4589   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4590   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4591   tmp->setCoords(tmp2);
4592   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4593   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4594   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4595   for(int i=1;i<nbOfLevsInVec;i++)
4596     {
4597       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4598       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4599       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4600       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4601       tmp->translate(vec);
4602       double tmp3[2],radius,alpha,alpha0;
4603       const double *p0=i+1<nbOfLevsInVec?begin:third;
4604       const double *p1=i+1<nbOfLevsInVec?end:begin;
4605       const double *p2=i+1<nbOfLevsInVec?third:end;
4606       double vecPlane[3]={
4607         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4608         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4609         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4610       };
4611       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4612       if(norm>1.e-7)
4613         {
4614           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4615           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4616           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4617           double s2=norm2;
4618           double c2=cos(asin(s2));
4619           double m[3][3]={
4620             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4621             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4622             {-vec2[1]*s2, vec2[0]*s2, c2}
4623           };
4624           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]};
4625           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]};
4626           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]};
4627           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4628           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]);
4629           double angle=acos(cosangle/(radius*radius));
4630           tmp->rotate(end,vecPlane,angle);
4631           
4632         }
4633       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4634     }
4635   return ret.retn();
4636 }
4637
4638 /*!
4639  * This method is private because not easy to use for end user. This method is const contrary to
4640  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4641  * the coords sorted slice by slice.
4642  * \param isQuad specifies presence of quadratic cells.
4643  */
4644 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4645 {
4646   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4647   int nbOf2DCells=getNumberOfCells();
4648   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4649   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4650   const int *conn=_nodal_connec->getConstPointer();
4651   const int *connI=_nodal_connec_index->getConstPointer();
4652   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4654   newConnI->alloc(nbOf3DCells+1,1);
4655   int *newConnIPtr=newConnI->getPointer();
4656   *newConnIPtr++=0;
4657   std::vector<int> newc;
4658   for(int j=0;j<nbOf2DCells;j++)
4659     {
4660       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4661       *newConnIPtr++=(int)newc.size();
4662     }
4663   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4664   int *newConnPtr=newConn->getPointer();
4665   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4666   newConnIPtr=newConnI->getPointer();
4667   for(int iz=0;iz<nbOf1DCells;iz++)
4668     {
4669       if(iz!=0)
4670         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4671       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4672         {
4673           int icell=(int)(iter-newc.begin());
4674           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4675             {
4676               if(*iter!=-1)
4677                 *newConnPtr=(*iter)+iz*deltaPerLev;
4678               else
4679                 *newConnPtr=-1;
4680             }
4681           else
4682             *newConnPtr=(*iter);
4683         }
4684     }
4685   ret->setConnectivity(newConn,newConnI,true);
4686   ret->setCoords(getCoords());
4687   return ret;
4688 }
4689
4690 /*!
4691  * Checks if \a this mesh is constituted by only quadratic cells.
4692  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4693  *  \throw If the coordinates array is not set.
4694  *  \throw If the nodal connectivity of cells is not defined.
4695  */
4696 bool MEDCouplingUMesh::isFullyQuadratic() const
4697 {
4698   checkFullyDefined();
4699   bool ret=true;
4700   int nbOfCells=getNumberOfCells();
4701   for(int i=0;i<nbOfCells && ret;i++)
4702     {
4703       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4704       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4705       ret=cm.isQuadratic();
4706     }
4707   return ret;
4708 }
4709
4710 /*!
4711  * Checks if \a this mesh includes any quadratic cell.
4712  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4713  *  \throw If the coordinates array is not set.
4714  *  \throw If the nodal connectivity of cells is not defined.
4715  */
4716 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4717 {
4718   checkFullyDefined();
4719   bool ret=false;
4720   int nbOfCells=getNumberOfCells();
4721   for(int i=0;i<nbOfCells && !ret;i++)
4722     {
4723       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4724       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4725       ret=cm.isQuadratic();
4726     }
4727   return ret;
4728 }
4729
4730 /*!
4731  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4732  * this mesh, it remains unchanged.
4733  *  \throw If the coordinates array is not set.
4734  *  \throw If the nodal connectivity of cells is not defined.
4735  */
4736 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4737 {
4738   checkFullyDefined();
4739   int nbOfCells=getNumberOfCells();
4740   int delta=0;
4741   const int *iciptr=_nodal_connec_index->getConstPointer();
4742   for(int i=0;i<nbOfCells;i++)
4743     {
4744       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4745       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4746       if(cm.isQuadratic())
4747         {
4748           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4749           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4750           if(!cml.isDynamic())
4751             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4752           else
4753             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4754         }
4755     }
4756   if(delta==0)
4757     return ;
4758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4760   const int *icptr=_nodal_connec->getConstPointer();
4761   newConn->alloc(getMeshLength()-delta,1);
4762   newConnI->alloc(nbOfCells+1,1);
4763   int *ocptr=newConn->getPointer();
4764   int *ociptr=newConnI->getPointer();
4765   *ociptr=0;
4766   _types.clear();
4767   for(int i=0;i<nbOfCells;i++,ociptr++)
4768     {
4769       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4770       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4771       if(!cm.isQuadratic())
4772         {
4773           _types.insert(type);
4774           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4775           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4776         }
4777       else
4778         {
4779           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4780           _types.insert(typel);
4781           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4782           int newNbOfNodes=cml.getNumberOfNodes();
4783           if(cml.isDynamic())
4784             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4785           *ocptr++=(int)typel;
4786           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4787           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4788         }
4789     }
4790   setConnectivity(newConn,newConnI,false);
4791 }
4792
4793 /*!
4794  * This method converts all linear cell in \a this to quadratic one.
4795  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4796  * 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)
4797  * 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.
4798  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4799  * end of the existing coordinates.
4800  * 
4801  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4802  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4803  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4804  * 
4805  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4806  *
4807  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4808  */
4809 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4810 {
4811   DataArrayInt *conn=0,*connI=0;
4812   DataArrayDouble *coords=0;
4813   std::set<INTERP_KERNEL::NormalizedCellType> types;
4814   checkFullyDefined();
4815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4816   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4817   int meshDim=getMeshDimension();
4818   switch(conversionType)
4819     {
4820     case 0:
4821       switch(meshDim)
4822         {
4823         case 1:
4824           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4825           connSafe=conn; connISafe=connI; coordsSafe=coords;
4826           break;
4827         case 2:
4828           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4829           connSafe=conn; connISafe=connI; coordsSafe=coords;
4830           break;
4831         case 3:
4832           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4833           connSafe=conn; connISafe=connI; coordsSafe=coords;
4834           break;
4835         default:
4836           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4837         }
4838       break;
4839     case 1:
4840       {
4841         switch(meshDim)
4842         {
4843         case 1:
4844           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4845           connSafe=conn; connISafe=connI; coordsSafe=coords;
4846           break;
4847         case 2:
4848           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4849           connSafe=conn; connISafe=connI; coordsSafe=coords;
4850           break;
4851         case 3:
4852           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4853           connSafe=conn; connISafe=connI; coordsSafe=coords;
4854           break;
4855         default:
4856           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4857         }
4858         break;
4859       }
4860     default:
4861       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4862     }
4863   setConnectivity(connSafe,connISafe,false);
4864   _types=types;
4865   setCoords(coordsSafe);
4866   return ret.retn();
4867 }
4868
4869 /*!
4870  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4871  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4872  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4873  */
4874 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4875 {
4876   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4880   int nbOfCells=getNumberOfCells();
4881   int nbOfNodes=getNumberOfNodes();
4882   const int *cPtr=_nodal_connec->getConstPointer();
4883   const int *icPtr=_nodal_connec_index->getConstPointer();
4884   int lastVal=0,offset=nbOfNodes;
4885   for(int i=0;i<nbOfCells;i++,icPtr++)
4886     {
4887       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4888       if(type==INTERP_KERNEL::NORM_SEG2)
4889         {
4890           types.insert(INTERP_KERNEL::NORM_SEG3);
4891           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4892           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4893           newConn->pushBackSilent(offset++);
4894           lastVal+=4;
4895           newConnI->pushBackSilent(lastVal);
4896           ret->pushBackSilent(i);
4897         }
4898       else
4899         {
4900           types.insert(type);
4901           lastVal+=(icPtr[1]-icPtr[0]);
4902           newConnI->pushBackSilent(lastVal);
4903           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4904         }
4905     }
4906   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4907   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4908   return ret.retn();
4909 }
4910
4911 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 throw(INTERP_KERNEL::Exception)
4912 {
4913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4916   //
4917   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4918   DataArrayInt *conn1D=0,*conn1DI=0;
4919   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4920   DataArrayDouble *coordsTmp=0;
4921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4922   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4924   const int *c1DPtr=conn1D->begin();
4925   const int *c1DIPtr=conn1DI->begin();
4926   int nbOfCells=getNumberOfCells();
4927   const int *cPtr=_nodal_connec->getConstPointer();
4928   const int *icPtr=_nodal_connec_index->getConstPointer();
4929   int lastVal=0;
4930   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4931     {
4932       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4933       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4934       if(!cm.isQuadratic())
4935         {
4936           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4937           types.insert(typ2); newConn->pushBackSilent(typ2);
4938           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4939           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4940             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4941           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4942           newConnI->pushBackSilent(lastVal);
4943           ret->pushBackSilent(i);
4944         }
4945       else
4946         {
4947           types.insert(typ);
4948           lastVal+=(icPtr[1]-icPtr[0]);
4949           newConnI->pushBackSilent(lastVal);
4950           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4951         }
4952     }
4953   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4954   return ret.retn();
4955 }
4956
4957 /*!
4958  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4959  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4960  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4961  */
4962 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4963 {
4964   
4965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4966   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4967   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4968 }
4969
4970 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4971 {
4972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4973   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4974   //
4975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4978   //
4979   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4980   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4981   DataArrayInt *conn1D=0,*conn1DI=0;
4982   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4983   DataArrayDouble *coordsTmp=0;
4984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4985   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4986   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4987   const int *c1DPtr=conn1D->begin();
4988   const int *c1DIPtr=conn1DI->begin();
4989   int nbOfCells=getNumberOfCells();
4990   const int *cPtr=_nodal_connec->getConstPointer();
4991   const int *icPtr=_nodal_connec_index->getConstPointer();
4992   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4993   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4994     {
4995       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4996       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4997       if(!cm.isQuadratic())
4998         {
4999           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5000           types.insert(typ2); newConn->pushBackSilent(typ2);
5001           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5002           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5003             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5004           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5005           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5006           newConnI->pushBackSilent(lastVal);
5007           ret->pushBackSilent(i);
5008         }
5009       else
5010         {
5011           types.insert(typ);
5012           lastVal+=(icPtr[1]-icPtr[0]);
5013           newConnI->pushBackSilent(lastVal);
5014           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5015         }
5016     }
5017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5018   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5019   return ret.retn();
5020 }
5021
5022 /*!
5023  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5024  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5025  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5026  */
5027 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5028 {
5029   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5030   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5031   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5032 }
5033
5034 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5035 {
5036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5037   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5039   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5040   //
5041   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5042   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5044   //
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5046   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5047   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5048   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5049   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5051   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5052   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5053   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5054   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5056   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5057   int nbOfCells=getNumberOfCells();
5058   const int *cPtr=_nodal_connec->getConstPointer();
5059   const int *icPtr=_nodal_connec_index->getConstPointer();
5060   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5061   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5062     {
5063       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5064       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5065       if(!cm.isQuadratic())
5066         {
5067           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5068           if(typ2==INTERP_KERNEL::NORM_ERROR)
5069             {
5070               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5071               throw INTERP_KERNEL::Exception(oss.str().c_str());
5072             }
5073           types.insert(typ2); newConn->pushBackSilent(typ2);
5074           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5075           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5076             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5077           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5078             {
5079               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5080               int tmpPos=newConn->getNumberOfTuples();
5081               newConn->pushBackSilent(nodeId2);
5082               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5083             }
5084           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5085           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5086           newConnI->pushBackSilent(lastVal);
5087           ret->pushBackSilent(i);
5088         }
5089       else
5090         {
5091           types.insert(typ);
5092           lastVal+=(icPtr[1]-icPtr[0]);
5093           newConnI->pushBackSilent(lastVal);
5094           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5095         }
5096     }
5097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5099   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5100   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5101   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5102   int *c=newConn->getPointer();
5103   const int *cI(newConnI->begin());
5104   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5105     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5106   offset=coordsTmp2Safe->getNumberOfTuples();
5107   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5108     c[cI[(*elt)+1]-1]+=offset;
5109   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5110   return ret.retn();
5111 }
5112
5113 /*!
5114  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5115  * so that the number of cells remains the same. Quadratic faces are converted to
5116  * polygons. This method works only for 2D meshes in
5117  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5118  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5119  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5120  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5121  *         a polylinized edge constituting the input polygon.
5122  *  \throw If the coordinates array is not set.
5123  *  \throw If the nodal connectivity of cells is not defined.
5124  *  \throw If \a this->getMeshDimension() != 2.
5125  *  \throw If \a this->getSpaceDimension() != 2.
5126  */
5127 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5128 {
5129   checkFullyDefined();
5130   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5132   double epsa=fabs(eps);
5133   if(epsa<std::numeric_limits<double>::min())
5134     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 !");
5135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5139   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5140   revDesc1=0; revDescIndx1=0;
5141   mDesc->tessellate2DCurve(eps);
5142   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5143   setCoords(mDesc->getCoords());
5144 }
5145
5146 /*!
5147  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5148  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5149  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5150  *         a sub-divided edge.
5151  *  \throw If the coordinates array is not set.
5152  *  \throw If the nodal connectivity of cells is not defined.
5153  *  \throw If \a this->getMeshDimension() != 1.
5154  *  \throw If \a this->getSpaceDimension() != 2.
5155  */
5156 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5157 {
5158   checkFullyDefined();
5159   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5161   double epsa=fabs(eps);
5162   if(epsa<std::numeric_limits<double>::min())
5163     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 !");
5164   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5165   int nbCells=getNumberOfCells();
5166   int nbNodes=getNumberOfNodes();
5167   const int *conn=_nodal_connec->getConstPointer();
5168   const int *connI=_nodal_connec_index->getConstPointer();
5169   const double *coords=_coords->getConstPointer();
5170   std::vector<double> addCoo;
5171   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5173   newConnI->alloc(nbCells+1,1);
5174   int *newConnIPtr=newConnI->getPointer();
5175   *newConnIPtr=0;
5176   int tmp1[3];
5177   INTERP_KERNEL::Node *tmp2[3];
5178   std::set<INTERP_KERNEL::NormalizedCellType> types;
5179   for(int i=0;i<nbCells;i++,newConnIPtr++)
5180     {
5181       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5182       if(cm.isQuadratic())
5183         {//assert(connI[i+1]-connI[i]-1==3)
5184           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5185           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5186           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5187           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5188           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5189           if(eac)
5190             {
5191               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5192               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5193               delete eac;
5194               newConnIPtr[1]=(int)newConn.size();
5195             }
5196           else
5197             {
5198               types.insert(INTERP_KERNEL::NORM_SEG2);
5199               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5200               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5201               newConnIPtr[1]=newConnIPtr[0]+3;
5202             }
5203         }
5204       else
5205         {
5206           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5207           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5208           newConnIPtr[1]=newConnIPtr[0]+3;
5209         }
5210     }
5211   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5212     return ;
5213   _types=types;
5214   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5216   newConnArr->alloc((int)newConn.size(),1);
5217   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5218   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5219   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5220   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5221   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5222   std::copy(addCoo.begin(),addCoo.end(),work);
5223   DataArrayDouble::SetArrayIn(newCoords,_coords);
5224   updateTime();
5225 }
5226
5227 /*!
5228  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5229  * In addition, returns an array mapping new cells to old ones. <br>
5230  * This method typically increases the number of cells in \a this mesh
5231  * but the number of nodes remains \b unchanged.
5232  * That's why the 3D splitting policies
5233  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5234  *  \param [in] policy - specifies a pattern used for splitting.
5235  * The semantic of \a policy is:
5236  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5237  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5238  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5239  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5240  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5241  *          an id of old cell producing it. The caller is to delete this array using
5242  *         decrRef() as it is no more needed. 
5243  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5244  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5245  *          and \a this->getMeshDimension() != 3. 
5246  *  \throw If \a policy is not one of the four discussed above.
5247  *  \throw If the nodal connectivity of cells is not defined.
5248  */
5249 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5250 {
5251   switch(policy)
5252     {
5253     case 0:
5254       return simplexizePol0();
5255     case 1:
5256       return simplexizePol1();
5257     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5258       return simplexizePlanarFace5();
5259     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5260       return simplexizePlanarFace6();
5261     default:
5262       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)");
5263     }
5264 }
5265
5266 /*!
5267  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5268  * - 1D: INTERP_KERNEL::NORM_SEG2
5269  * - 2D: INTERP_KERNEL::NORM_TRI3
5270  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5271  *
5272  * This method is useful for users that need to use P1 field services as
5273  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5274  * All these methods need mesh support containing only simplex cells.
5275  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5276  *  \throw If the coordinates array is not set.
5277  *  \throw If the nodal connectivity of cells is not defined.
5278  *  \throw If \a this->getMeshDimension() < 1.
5279  */
5280 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5281 {
5282   checkFullyDefined();
5283   int mdim=getMeshDimension();
5284   if(mdim<1 || mdim>3)
5285     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5286   int nbCells=getNumberOfCells();
5287   const int *conn=_nodal_connec->getConstPointer();
5288   const int *connI=_nodal_connec_index->getConstPointer();
5289   for(int i=0;i<nbCells;i++)
5290     {
5291       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5292       if(!cm.isSimplex())
5293         return false;
5294     }
5295   return true;
5296 }
5297
5298 /*!
5299  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5300  */
5301 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5302 {
5303   checkConnectivityFullyDefined();
5304   if(getMeshDimension()!=2)
5305     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5306   int nbOfCells=getNumberOfCells();
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5308   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5309   ret->alloc(nbOfCells+nbOfCutCells,1);
5310   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5311   int *retPt=ret->getPointer();
5312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5313   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5314   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5315   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5316   int *pt=newConn->getPointer();
5317   int *ptI=newConnI->getPointer();
5318   ptI[0]=0;
5319   const int *oldc=_nodal_connec->getConstPointer();
5320   const int *ci=_nodal_connec_index->getConstPointer();
5321   for(int i=0;i<nbOfCells;i++,ci++)
5322     {
5323       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5324         {
5325           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5326                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5327           pt=std::copy(tmp,tmp+8,pt);
5328           ptI[1]=ptI[0]+4;
5329           ptI[2]=ptI[0]+8;
5330           *retPt++=i;
5331           *retPt++=i;
5332           ptI+=2;
5333         }
5334       else
5335         {
5336           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5337           ptI[1]=ptI[0]+ci[1]-ci[0];
5338           ptI++;
5339           *retPt++=i;
5340         }
5341     }
5342   _nodal_connec->decrRef();
5343   _nodal_connec=newConn.retn();
5344   _nodal_connec_index->decrRef();
5345   _nodal_connec_index=newConnI.retn();
5346   computeTypes();
5347   updateTime();
5348   return ret.retn();
5349 }
5350
5351 /*!
5352  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5353  */
5354 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5355 {
5356   checkConnectivityFullyDefined();
5357   if(getMeshDimension()!=2)
5358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5359   int nbOfCells=getNumberOfCells();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5361   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5362   ret->alloc(nbOfCells+nbOfCutCells,1);
5363   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5364   int *retPt=ret->getPointer();
5365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5367   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5368   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5369   int *pt=newConn->getPointer();
5370   int *ptI=newConnI->getPointer();
5371   ptI[0]=0;
5372   const int *oldc=_nodal_connec->getConstPointer();
5373   const int *ci=_nodal_connec_index->getConstPointer();
5374   for(int i=0;i<nbOfCells;i++,ci++)
5375     {
5376       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5377         {
5378           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5379                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5380           pt=std::copy(tmp,tmp+8,pt);
5381           ptI[1]=ptI[0]+4;
5382           ptI[2]=ptI[0]+8;
5383           *retPt++=i;
5384           *retPt++=i;
5385           ptI+=2;
5386         }
5387       else
5388         {
5389           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5390           ptI[1]=ptI[0]+ci[1]-ci[0];
5391           ptI++;
5392           *retPt++=i;
5393         }
5394     }
5395   _nodal_connec->decrRef();
5396   _nodal_connec=newConn.retn();
5397   _nodal_connec_index->decrRef();
5398   _nodal_connec_index=newConnI.retn();
5399   computeTypes();
5400   updateTime();
5401   return ret.retn();
5402 }
5403
5404 /*!
5405  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5406  */
5407 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5408 {
5409   checkConnectivityFullyDefined();
5410   if(getMeshDimension()!=3)
5411     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5412   int nbOfCells=getNumberOfCells();
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5414   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5415   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5416   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5417   int *retPt=ret->getPointer();
5418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5420   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5421   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5422   int *pt=newConn->getPointer();
5423   int *ptI=newConnI->getPointer();
5424   ptI[0]=0;
5425   const int *oldc=_nodal_connec->getConstPointer();
5426   const int *ci=_nodal_connec_index->getConstPointer();
5427   for(int i=0;i<nbOfCells;i++,ci++)
5428     {
5429       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5430         {
5431           for(int j=0;j<5;j++,pt+=5,ptI++)
5432             {
5433               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5434               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];
5435               *retPt++=i;
5436               ptI[1]=ptI[0]+5;
5437             }
5438         }
5439       else
5440         {
5441           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5442           ptI[1]=ptI[0]+ci[1]-ci[0];
5443           ptI++;
5444           *retPt++=i;
5445         }
5446     }
5447   _nodal_connec->decrRef();
5448   _nodal_connec=newConn.retn();
5449   _nodal_connec_index->decrRef();
5450   _nodal_connec_index=newConnI.retn();
5451   computeTypes();
5452   updateTime();
5453   return ret.retn();
5454 }
5455
5456 /*!
5457  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5458  */
5459 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5460 {
5461   checkConnectivityFullyDefined();
5462   if(getMeshDimension()!=3)
5463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5464   int nbOfCells=getNumberOfCells();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5466   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5467   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5468   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5469   int *retPt=ret->getPointer();
5470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5472   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5473   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5474   int *pt=newConn->getPointer();
5475   int *ptI=newConnI->getPointer();
5476   ptI[0]=0;
5477   const int *oldc=_nodal_connec->getConstPointer();
5478   const int *ci=_nodal_connec_index->getConstPointer();
5479   for(int i=0;i<nbOfCells;i++,ci++)
5480     {
5481       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5482         {
5483           for(int j=0;j<6;j++,pt+=5,ptI++)
5484             {
5485               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5486               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];
5487               *retPt++=i;
5488               ptI[1]=ptI[0]+5;
5489             }
5490         }
5491       else
5492         {
5493           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5494           ptI[1]=ptI[0]+ci[1]-ci[0];
5495           ptI++;
5496           *retPt++=i;
5497         }
5498     }
5499   _nodal_connec->decrRef();
5500   _nodal_connec=newConn.retn();
5501   _nodal_connec_index->decrRef();
5502   _nodal_connec_index=newConnI.retn();
5503   computeTypes();
5504   updateTime();
5505   return ret.retn();
5506 }
5507
5508 /*!
5509  * 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.
5510  * This method completly ignore coordinates.
5511  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5512  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5513  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5514  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5515  */
5516 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5517 {
5518   checkFullyDefined();
5519   if(getMeshDimension()!=2)
5520     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5521   int nbOfCells=getNumberOfCells();
5522   int *connI=_nodal_connec_index->getPointer();
5523   int newConnLgth=0;
5524   for(int i=0;i<nbOfCells;i++,connI++)
5525     {
5526       int offset=descIndex[i];
5527       int nbOfEdges=descIndex[i+1]-offset;
5528       //
5529       bool ddirect=desc[offset+nbOfEdges-1]>0;
5530       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5531       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5532       for(int j=0;j<nbOfEdges;j++)
5533         {
5534           bool direct=desc[offset+j]>0;
5535           int edgeId=std::abs(desc[offset+j])-1;
5536           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5537             {
5538               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5539               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5540               int ref2=direct?id1:id2;
5541               if(ref==ref2)
5542                 {
5543                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5544                   newConnLgth+=nbOfSubNodes-1;
5545                   ref=direct?id2:id1;
5546                 }
5547               else
5548                 {
5549                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5550                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5551                 }
5552             }
5553           else
5554             {
5555               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5556             }
5557         }
5558       newConnLgth++;//+1 is for cell type
5559       connI[1]=newConnLgth;
5560     }
5561   //
5562   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5563   newConn->alloc(newConnLgth,1);
5564   int *work=newConn->getPointer();
5565   for(int i=0;i<nbOfCells;i++)
5566     {
5567       *work++=INTERP_KERNEL::NORM_POLYGON;
5568       int offset=descIndex[i];
5569       int nbOfEdges=descIndex[i+1]-offset;
5570       for(int j=0;j<nbOfEdges;j++)
5571         {
5572           bool direct=desc[offset+j]>0;
5573           int edgeId=std::abs(desc[offset+j])-1;
5574           if(direct)
5575             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5576           else
5577             {
5578               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5579               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5580               work=std::copy(it,it+nbOfSubNodes-1,work);
5581             }
5582         }
5583     }
5584   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5585   _types.clear();
5586   if(nbOfCells>0)
5587     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5588 }
5589
5590 /*!
5591  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5592  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5593  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5594  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5595  * so it can be useful to call mergeNodes() before calling this method.
5596  *  \throw If \a this->getMeshDimension() <= 1.
5597  *  \throw If the coordinates array is not set.
5598  *  \throw If the nodal connectivity of cells is not defined.
5599  */
5600 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5601 {
5602   checkFullyDefined();
5603   if(getMeshDimension()<=1)
5604     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5605   int nbOfCells=getNumberOfCells();
5606   if(nbOfCells<1)
5607     return ;
5608   int initMeshLgth=getMeshLength();
5609   int *conn=_nodal_connec->getPointer();
5610   int *index=_nodal_connec_index->getPointer();
5611   int posOfCurCell=0;
5612   int newPos=0;
5613   int lgthOfCurCell;
5614   for(int i=0;i<nbOfCells;i++)
5615     {
5616       lgthOfCurCell=index[i+1]-posOfCurCell;
5617       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5618       int newLgth;
5619       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5620                                                                                                      conn+newPos+1,newLgth);
5621       conn[newPos]=newType;
5622       newPos+=newLgth+1;
5623       posOfCurCell=index[i+1];
5624       index[i+1]=newPos;
5625     }
5626   if(newPos!=initMeshLgth)
5627     _nodal_connec->reAlloc(newPos);
5628   computeTypes();
5629 }
5630
5631 /*!
5632  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5633  * A cell is considered to be oriented correctly if an angle between its
5634  * normal vector and a given vector is less than \c PI / \c 2.
5635  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5636  *         cells. 
5637  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5638  *         checked.
5639  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5640  *         is not cleared before filling in.
5641  *  \throw If \a this->getMeshDimension() != 2.
5642  *  \throw If \a this->getSpaceDimension() != 3.
5643  *
5644  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5645  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5646  */
5647 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5648 {
5649   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5650     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5651   int nbOfCells=getNumberOfCells();
5652   const int *conn=_nodal_connec->getConstPointer();
5653   const int *connI=_nodal_connec_index->getConstPointer();
5654   const double *coordsPtr=_coords->getConstPointer();
5655   for(int i=0;i<nbOfCells;i++)
5656     {
5657       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5658       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5659         {
5660           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5661           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5662             cells.push_back(i);
5663         }
5664     }
5665 }
5666
5667 /*!
5668  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5669  * considered to be oriented correctly if an angle between its normal vector and a
5670  * given vector is less than \c PI / \c 2. 
5671  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5672  *         cells. 
5673  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5674  *         checked.
5675  *  \throw If \a this->getMeshDimension() != 2.
5676  *  \throw If \a this->getSpaceDimension() != 3.
5677  *
5678  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5679  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5680  */
5681 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5682 {
5683   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5684     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5685   int nbOfCells=getNumberOfCells();
5686   int *conn=_nodal_connec->getPointer();
5687   const int *connI=_nodal_connec_index->getConstPointer();
5688   const double *coordsPtr=_coords->getConstPointer();
5689   bool isModified=false;
5690   for(int i=0;i<nbOfCells;i++)
5691     {
5692       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5693       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5694         {
5695           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5696           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5697             {
5698               isModified=true;
5699               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5700               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5701               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5702             }
5703         }
5704     }
5705   if(isModified)
5706     _nodal_connec->declareAsNew();
5707   updateTime();
5708 }
5709
5710 /*!
5711  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5712  * oriented facets. The normal vector of the facet should point out of the cell.
5713  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5714  *         is not cleared before filling in.
5715  *  \throw If \a this->getMeshDimension() != 3.
5716  *  \throw If \a this->getSpaceDimension() != 3.
5717  *  \throw If the coordinates array is not set.
5718  *  \throw If the nodal connectivity of cells is not defined.
5719  *
5720  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5721  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5722  */
5723 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5724 {
5725   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5726     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5727   int nbOfCells=getNumberOfCells();
5728   const int *conn=_nodal_connec->getConstPointer();
5729   const int *connI=_nodal_connec_index->getConstPointer();
5730   const double *coordsPtr=_coords->getConstPointer();
5731   for(int i=0;i<nbOfCells;i++)
5732     {
5733       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5734       if(type==INTERP_KERNEL::NORM_POLYHED)
5735         {
5736           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5737             cells.push_back(i);
5738         }
5739     }
5740 }
5741
5742 /*!
5743  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5744  * out of the cell. 
5745  *  \throw If \a this->getMeshDimension() != 3.
5746  *  \throw If \a this->getSpaceDimension() != 3.
5747  *  \throw If the coordinates array is not set.
5748  *  \throw If the nodal connectivity of cells is not defined.
5749  *  \throw If the reparation fails.
5750  *
5751  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5752  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5753  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5754  */
5755 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5756 {
5757   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5758     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5759   int nbOfCells=getNumberOfCells();
5760   int *conn=_nodal_connec->getPointer();
5761   const int *connI=_nodal_connec_index->getConstPointer();
5762   const double *coordsPtr=_coords->getConstPointer();
5763   for(int i=0;i<nbOfCells;i++)
5764     {
5765       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5766       if(type==INTERP_KERNEL::NORM_POLYHED)
5767         {
5768           try
5769             {
5770               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5771                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5772             }
5773           catch(INTERP_KERNEL::Exception& e)
5774             {
5775               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5776               throw INTERP_KERNEL::Exception(oss.str().c_str());
5777             }
5778         }
5779     }
5780   updateTime();
5781 }
5782
5783 /*!
5784  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5785  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5786  * according to which the first facet of the cell should be oriented to have the normal vector
5787  * pointing out of cell.
5788  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5789  *         cells. The caller is to delete this array using decrRef() as it is no more
5790  *         needed. 
5791  *  \throw If \a this->getMeshDimension() != 3.
5792  *  \throw If \a this->getSpaceDimension() != 3.
5793  *  \throw If the coordinates array is not set.
5794  *  \throw If the nodal connectivity of cells is not defined.
5795  *
5796  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5797  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5798  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5799  */
5800 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5801 {
5802   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5803   if(getMeshDimension()!=3)
5804     throw INTERP_KERNEL::Exception(msg);
5805   int spaceDim=getSpaceDimension();
5806   if(spaceDim!=3)
5807     throw INTERP_KERNEL::Exception(msg);
5808   //
5809   int nbOfCells=getNumberOfCells();
5810   int *conn=_nodal_connec->getPointer();
5811   const int *connI=_nodal_connec_index->getConstPointer();
5812   const double *coo=getCoords()->getConstPointer();
5813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5814   for(int i=0;i<nbOfCells;i++)
5815     {
5816       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5817       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5818         {
5819           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5820             {
5821               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5822               cells->pushBackSilent(i);
5823             }
5824         }
5825     }
5826   return cells.retn();
5827 }
5828
5829 /*!
5830  * This method is a faster method to correct orientation of all 3D cells in \a this.
5831  * 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.
5832  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5833  * 
5834  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5835  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5836  */
5837 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5838 {
5839   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5840     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5841   int nbOfCells=getNumberOfCells();
5842   int *conn=_nodal_connec->getPointer();
5843   const int *connI=_nodal_connec_index->getConstPointer();
5844   const double *coordsPtr=_coords->getConstPointer();
5845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5846   for(int i=0;i<nbOfCells;i++)
5847     {
5848       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5849       switch(type)
5850         {
5851         case INTERP_KERNEL::NORM_TETRA4:
5852           {
5853             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5854               {
5855                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5856                 ret->pushBackSilent(i);
5857               }
5858             break;
5859           }
5860         case INTERP_KERNEL::NORM_PYRA5:
5861           {
5862             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5863               {
5864                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5865                 ret->pushBackSilent(i);
5866               }
5867             break;
5868           }
5869         case INTERP_KERNEL::NORM_PENTA6:
5870         case INTERP_KERNEL::NORM_HEXA8:
5871         case INTERP_KERNEL::NORM_HEXGP12:
5872           {
5873             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5874               {
5875                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5876                 ret->pushBackSilent(i);
5877               }
5878             break;
5879           }
5880         case INTERP_KERNEL::NORM_POLYHED:
5881           {
5882             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5883               {
5884                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5885                 ret->pushBackSilent(i);
5886               }
5887             break;
5888           }
5889         default:
5890           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 !");
5891         }
5892     }
5893   updateTime();
5894   return ret.retn();
5895 }
5896
5897 /*!
5898  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5899  * If it is not the case an exception will be thrown.
5900  * This method is fast because the first cell of \a this is used to compute the plane.
5901  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5902  * \param pos output of size at least 3 used to store a point owned of searched plane.
5903  */
5904 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5905 {
5906   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5907     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5908   const int *conn=_nodal_connec->getConstPointer();
5909   const int *connI=_nodal_connec_index->getConstPointer();
5910   const double *coordsPtr=_coords->getConstPointer();
5911   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5912   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5913 }
5914
5915 /*!
5916  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5917  * cells. Currently cells of the following types are treated:
5918  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5919  * For a cell of other type an exception is thrown.
5920  * Space dimension of a 2D mesh can be either 2 or 3.
5921  * The Edge Ratio of a cell \f$t\f$ is: 
5922  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5923  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5924  *  the smallest edge lengths of \f$t\f$.
5925  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5926  *          cells and one time, lying on \a this mesh. The caller is to delete this
5927  *          field using decrRef() as it is no more needed. 
5928  *  \throw If the coordinates array is not set.
5929  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5930  *  \throw If the connectivity data array has more than one component.
5931  *  \throw If the connectivity data array has a named component.
5932  *  \throw If the connectivity index data array has more than one component.
5933  *  \throw If the connectivity index data array has a named component.
5934  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5935  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5936  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5937  */
5938 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5939 {
5940   checkCoherency();
5941   int spaceDim=getSpaceDimension();
5942   int meshDim=getMeshDimension();
5943   if(spaceDim!=2 && spaceDim!=3)
5944     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5945   if(meshDim!=2 && meshDim!=3)
5946     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5947   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5948   ret->setMesh(this);
5949   int nbOfCells=getNumberOfCells();
5950   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5951   arr->alloc(nbOfCells,1);
5952   double *pt=arr->getPointer();
5953   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5954   const int *conn=_nodal_connec->getConstPointer();
5955   const int *connI=_nodal_connec_index->getConstPointer();
5956   const double *coo=_coords->getConstPointer();
5957   double tmp[12];
5958   for(int i=0;i<nbOfCells;i++,pt++)
5959     {
5960       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5961       switch(t)
5962         {
5963           case INTERP_KERNEL::NORM_TRI3:
5964             {
5965               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5966               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5967               break;
5968             }
5969           case INTERP_KERNEL::NORM_QUAD4:
5970             {
5971               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5972               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5973               break;
5974             }
5975           case INTERP_KERNEL::NORM_TETRA4:
5976             {
5977               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5978               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5979               break;
5980             }
5981         default:
5982           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5983         }
5984       conn+=connI[i+1]-connI[i];
5985     }
5986   ret->setName("EdgeRatio");
5987   ret->synchronizeTimeWithSupport();
5988   return ret.retn();
5989 }
5990
5991 /*!
5992  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5993  * cells. Currently cells of the following types are treated:
5994  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5995  * For a cell of other type an exception is thrown.
5996  * Space dimension of a 2D mesh can be either 2 or 3.
5997  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5998  *          cells and one time, lying on \a this mesh. The caller is to delete this
5999  *          field using decrRef() as it is no more needed. 
6000  *  \throw If the coordinates array is not set.
6001  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6002  *  \throw If the connectivity data array has more than one component.
6003  *  \throw If the connectivity data array has a named component.
6004  *  \throw If the connectivity index data array has more than one component.
6005  *  \throw If the connectivity index data array has a named component.
6006  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6007  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6008  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6009  */
6010 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6011 {
6012   checkCoherency();
6013   int spaceDim=getSpaceDimension();
6014   int meshDim=getMeshDimension();
6015   if(spaceDim!=2 && spaceDim!=3)
6016     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6017   if(meshDim!=2 && meshDim!=3)
6018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6019   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6020   ret->setMesh(this);
6021   int nbOfCells=getNumberOfCells();
6022   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6023   arr->alloc(nbOfCells,1);
6024   double *pt=arr->getPointer();
6025   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6026   const int *conn=_nodal_connec->getConstPointer();
6027   const int *connI=_nodal_connec_index->getConstPointer();
6028   const double *coo=_coords->getConstPointer();
6029   double tmp[12];
6030   for(int i=0;i<nbOfCells;i++,pt++)
6031     {
6032       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6033       switch(t)
6034         {
6035           case INTERP_KERNEL::NORM_TRI3:
6036             {
6037               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6038               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6039               break;
6040             }
6041           case INTERP_KERNEL::NORM_QUAD4:
6042             {
6043               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6044               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6045               break;
6046             }
6047           case INTERP_KERNEL::NORM_TETRA4:
6048             {
6049               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6050               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6051               break;
6052             }
6053         default:
6054           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6055         }
6056       conn+=connI[i+1]-connI[i];
6057     }
6058   ret->setName("AspectRatio");
6059   ret->synchronizeTimeWithSupport();
6060   return ret.retn();
6061 }
6062
6063 /*!
6064  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6065  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6066  * treated: INTERP_KERNEL::NORM_QUAD4.
6067  * For a cell of other type an exception is thrown.
6068  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6069  *          cells and one time, lying on \a this mesh. The caller is to delete this
6070  *          field using decrRef() as it is no more needed. 
6071  *  \throw If the coordinates array is not set.
6072  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6073  *  \throw If the connectivity data array has more than one component.
6074  *  \throw If the connectivity data array has a named component.
6075  *  \throw If the connectivity index data array has more than one component.
6076  *  \throw If the connectivity index data array has a named component.
6077  *  \throw If \a this->getMeshDimension() != 2.
6078  *  \throw If \a this->getSpaceDimension() != 3.
6079  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6080  */
6081 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6082 {
6083   checkCoherency();
6084   int spaceDim=getSpaceDimension();
6085   int meshDim=getMeshDimension();
6086   if(spaceDim!=3)
6087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6088   if(meshDim!=2)
6089     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6090   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6091   ret->setMesh(this);
6092   int nbOfCells=getNumberOfCells();
6093   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6094   arr->alloc(nbOfCells,1);
6095   double *pt=arr->getPointer();
6096   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6097   const int *conn=_nodal_connec->getConstPointer();
6098   const int *connI=_nodal_connec_index->getConstPointer();
6099   const double *coo=_coords->getConstPointer();
6100   double tmp[12];
6101   for(int i=0;i<nbOfCells;i++,pt++)
6102     {
6103       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6104       switch(t)
6105         {
6106           case INTERP_KERNEL::NORM_QUAD4:
6107             {
6108               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6109               *pt=INTERP_KERNEL::quadWarp(tmp);
6110               break;
6111             }
6112         default:
6113           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6114         }
6115       conn+=connI[i+1]-connI[i];
6116     }
6117   ret->setName("Warp");
6118   ret->synchronizeTimeWithSupport();
6119   return ret.retn();
6120 }
6121
6122
6123 /*!
6124  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6125  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6126  * treated: INTERP_KERNEL::NORM_QUAD4.
6127  * For a cell of other type an exception is thrown.
6128  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6129  *          cells and one time, lying on \a this mesh. The caller is to delete this
6130  *          field using decrRef() as it is no more needed. 
6131  *  \throw If the coordinates array is not set.
6132  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6133  *  \throw If the connectivity data array has more than one component.
6134  *  \throw If the connectivity data array has a named component.
6135  *  \throw If the connectivity index data array has more than one component.
6136  *  \throw If the connectivity index data array has a named component.
6137  *  \throw If \a this->getMeshDimension() != 2.
6138  *  \throw If \a this->getSpaceDimension() != 3.
6139  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6140  */
6141 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6142 {
6143   checkCoherency();
6144   int spaceDim=getSpaceDimension();
6145   int meshDim=getMeshDimension();
6146   if(spaceDim!=3)
6147     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6148   if(meshDim!=2)
6149     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6150   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6151   ret->setMesh(this);
6152   int nbOfCells=getNumberOfCells();
6153   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6154   arr->alloc(nbOfCells,1);
6155   double *pt=arr->getPointer();
6156   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6157   const int *conn=_nodal_connec->getConstPointer();
6158   const int *connI=_nodal_connec_index->getConstPointer();
6159   const double *coo=_coords->getConstPointer();
6160   double tmp[12];
6161   for(int i=0;i<nbOfCells;i++,pt++)
6162     {
6163       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6164       switch(t)
6165         {
6166           case INTERP_KERNEL::NORM_QUAD4:
6167             {
6168               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6169               *pt=INTERP_KERNEL::quadSkew(tmp);
6170               break;
6171             }
6172         default:
6173           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6174         }
6175       conn+=connI[i+1]-connI[i];
6176     }
6177   ret->setName("Skew");
6178   ret->synchronizeTimeWithSupport();
6179   return ret.retn();
6180 }
6181
6182 /*!
6183  * This method aggregate the bbox of each cell and put it into bbox parameter.
6184  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6185  */
6186 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6187 {
6188   int spaceDim=getSpaceDimension();
6189   int nbOfCells=getNumberOfCells();
6190   bbox.resize(2*nbOfCells*spaceDim);
6191   for(int i=0;i<nbOfCells*spaceDim;i++)
6192     {
6193       bbox[2*i]=std::numeric_limits<double>::max();
6194       bbox[2*i+1]=-std::numeric_limits<double>::max();
6195     }
6196   const double *coordsPtr=_coords->getConstPointer();
6197   const int *conn=_nodal_connec->getConstPointer();
6198   const int *connI=_nodal_connec_index->getConstPointer();
6199   for(int i=0;i<nbOfCells;i++)
6200     {
6201       int offset=connI[i]+1;
6202       int nbOfNodesForCell=connI[i+1]-offset;
6203       for(int j=0;j<nbOfNodesForCell;j++)
6204         {
6205           int nodeId=conn[offset+j];
6206           if(nodeId>=0)
6207             for(int k=0;k<spaceDim;k++)
6208               {
6209                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6210                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6211               }
6212         }
6213     }
6214 }
6215
6216 /// @cond INTERNAL
6217
6218 namespace ParaMEDMEMImpl
6219 {
6220   class ConnReader
6221   {
6222   public:
6223     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6224     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6225   private:
6226     const int *_conn;
6227     int _val;
6228   };
6229
6230   class ConnReader2
6231   {
6232   public:
6233     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6234     bool operator() (const int& pos) { return _conn[pos]==_val; }
6235   private:
6236     const int *_conn;
6237     int _val;
6238   };
6239 }
6240
6241 /// @endcond
6242
6243 /*!
6244  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6245  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6246  * \a this is composed in cell types.
6247  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6248  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6249  * This parameter is kept only for compatibility with other methode listed above.
6250  */
6251 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6252 {
6253   checkConnectivityFullyDefined();
6254   const int *conn=_nodal_connec->getConstPointer();
6255   const int *connI=_nodal_connec_index->getConstPointer();
6256   const int *work=connI;
6257   int nbOfCells=getNumberOfCells();
6258   std::size_t n=getAllTypes().size();
6259   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6260   std::set<INTERP_KERNEL::NormalizedCellType> types;
6261   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6262     {
6263       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6264       if(types.find(typ)!=types.end())
6265         {
6266           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6267           oss << " is not contiguous !";
6268           throw INTERP_KERNEL::Exception(oss.str().c_str());
6269         }
6270       types.insert(typ);
6271       ret[3*i]=typ;
6272       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6273       ret[3*i+1]=(int)std::distance(work,work2);
6274       work=work2;
6275     }
6276   return ret;
6277 }
6278
6279 /*!
6280  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6281  * only for types cell, type node is not managed.
6282  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6283  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6284  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6285  * If 2 or more same geometric type is in \a code and exception is thrown too.
6286  *
6287  * This method firstly checks
6288  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6289  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6290  * an exception is thrown too.
6291  * 
6292  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6293  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6294  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6295  */
6296 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6297 {
6298   if(code.empty())
6299     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6300   std::size_t sz=code.size();
6301   std::size_t n=sz/3;
6302   if(sz%3!=0)
6303     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6304   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6305   int nb=0;
6306   for(std::size_t i=0;i<n;i++)
6307     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6308       {
6309         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6310         nb+=code[3*i+1];
6311         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6312           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6313       }
6314   if(types.size()!=n)
6315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6316   if(idsPerType.empty())
6317     {
6318       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6319         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6320       if(types.size()==_types.size())
6321         return 0;
6322     }
6323   DataArrayInt *ret=DataArrayInt::New();
6324   ret->alloc(nb,1);
6325   int *retPtr=ret->getPointer();
6326   const int *connI=_nodal_connec_index->getConstPointer();
6327   const int *conn=_nodal_connec->getConstPointer();
6328   int nbOfCells=getNumberOfCells();
6329   const int *i=connI;
6330   int kk=0;
6331   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6332     {
6333       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6334       int offset=(int)std::distance(connI,i);
6335       if(code[3*kk+2]==-1)
6336         {
6337           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6338           std::size_t pos2=std::distance(i,j);
6339           for(std::size_t k=0;k<pos2;k++)
6340             *retPtr++=(int)k+offset;
6341           i=j;
6342         }
6343       else
6344         {
6345           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6346                                 retPtr,std::bind2nd(std::plus<int>(),offset));
6347         }
6348     }
6349   return ret;
6350 }
6351
6352 /*!
6353  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6354  * 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.
6355  * 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.
6356  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6357  * 
6358  * \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.
6359  * \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,
6360  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6361  * \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.
6362  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6363  * \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
6364  */
6365 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6366 {
6367   if(!profile)
6368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6369   if(profile->getNumberOfComponents()!=1)
6370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6371   checkConnectivityFullyDefined();
6372   const int *conn=_nodal_connec->getConstPointer();
6373   const int *connI=_nodal_connec_index->getConstPointer();
6374   int nbOfCells=getNumberOfCells();
6375   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6376   std::vector<int> typeRangeVals(1);
6377   for(const int *i=connI;i!=connI+nbOfCells;)
6378     {
6379       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6380       if(std::find(types.begin(),types.end(),curType)!=types.end())
6381         {
6382           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6383         }
6384       types.push_back(curType);
6385       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6386       typeRangeVals.push_back((int)std::distance(connI,i));
6387     }
6388   //
6389   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6390   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6394   //
6395   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6396   code.resize(3*nbOfCastsFinal);
6397   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6398   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6399   for(int i=0;i<nbOfCastsFinal;i++)
6400     {
6401       int castId=castsPresent->getIJ(i,0);
6402       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6403       idsInPflPerType2.push_back(tmp3);
6404       code[3*i]=(int)types[castId];
6405       code[3*i+1]=tmp3->getNumberOfTuples();
6406       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6407       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6408         {
6409           tmp4->copyStringInfoFrom(*profile);
6410           idsPerType2.push_back(tmp4);
6411           code[3*i+2]=(int)idsPerType2.size()-1;
6412         }
6413       else
6414         {
6415           code[3*i+2]=-1;
6416         }
6417     }
6418   std::size_t sz2=idsInPflPerType2.size();
6419   idsInPflPerType.resize(sz2);
6420   for(std::size_t i=0;i<sz2;i++)
6421     {
6422       DataArrayInt *locDa=idsInPflPerType2[i];
6423       locDa->incrRef();
6424       idsInPflPerType[i]=locDa;
6425     }
6426   std::size_t sz=idsPerType2.size();
6427   idsPerType.resize(sz);
6428   for(std::size_t i=0;i<sz;i++)
6429     {
6430       DataArrayInt *locDa=idsPerType2[i];
6431       locDa->incrRef();
6432       idsPerType[i]=locDa;
6433     }
6434 }
6435
6436 /*!
6437  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6438  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6439  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6440  * 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.
6441  */
6442 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6443 {
6444   checkFullyDefined();
6445   nM1LevMesh->checkFullyDefined();
6446   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6447     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6448   if(_coords!=nM1LevMesh->getCoords())
6449     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6452   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6454   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6455   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6456   tmp->setConnectivity(tmp0,tmp1);
6457   tmp->renumberCells(ret0->getConstPointer(),false);
6458   revDesc=tmp->getNodalConnectivity();
6459   revDescIndx=tmp->getNodalConnectivityIndex();
6460   DataArrayInt *ret=0;
6461   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6462     {
6463       int tmp2;
6464       ret->getMaxValue(tmp2);
6465       ret->decrRef();
6466       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6467       throw INTERP_KERNEL::Exception(oss.str().c_str());
6468     }
6469   nM1LevMeshIds=ret;
6470   //
6471   revDesc->incrRef();
6472   revDescIndx->incrRef();
6473   ret1->incrRef();
6474   ret0->incrRef();
6475   meshnM1Old2New=ret0;
6476   return ret1;
6477 }
6478
6479 /*!
6480  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6481  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6482  * in "Old to New" mode.
6483  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6484  *          this array using decrRef() as it is no more needed.
6485  *  \throw If the nodal connectivity of cells is not defined.
6486  */
6487 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6488 {
6489   checkConnectivityFullyDefined();
6490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6491   renumberCells(ret->getConstPointer(),false);
6492   return ret.retn();
6493 }
6494
6495 /*!
6496  * This methods checks that cells are sorted by their types.
6497  * This method makes asumption (no check) that connectivity is correctly set before calling.
6498  */
6499 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6500 {
6501   checkFullyDefined();
6502   const int *conn=_nodal_connec->getConstPointer();
6503   const int *connI=_nodal_connec_index->getConstPointer();
6504   int nbOfCells=getNumberOfCells();
6505   std::set<INTERP_KERNEL::NormalizedCellType> types;
6506   for(const int *i=connI;i!=connI+nbOfCells;)
6507     {
6508       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6509       if(types.find(curType)!=types.end())
6510         return false;
6511       types.insert(curType);
6512       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6513     }
6514   return true;
6515 }
6516
6517 /*!
6518  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6519  * The geometric type order is specified by MED file.
6520  * 
6521  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6522  */
6523 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6524 {
6525   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6526 }
6527
6528 /*!
6529  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6530  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6531  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6532  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6533  */
6534 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6535 {
6536   checkFullyDefined();
6537   const int *conn=_nodal_connec->getConstPointer();
6538   const int *connI=_nodal_connec_index->getConstPointer();
6539   int nbOfCells=getNumberOfCells();
6540   if(nbOfCells==0)
6541     return true;
6542   int lastPos=-1;
6543   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6544   for(const int *i=connI;i!=connI+nbOfCells;)
6545     {
6546       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6547       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6548       if(isTypeExists!=orderEnd)
6549         {
6550           int pos=(int)std::distance(orderBg,isTypeExists);
6551           if(pos<=lastPos)
6552             return false;
6553           lastPos=pos;
6554           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6555         }
6556       else
6557         {
6558           if(sg.find(curType)==sg.end())
6559             {
6560               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6561               sg.insert(curType);
6562             }
6563           else
6564             return false;
6565         }
6566     }
6567   return true;
6568 }
6569
6570 /*!
6571  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6572  * 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
6573  * 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'.
6574  */
6575 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6576 {
6577   checkConnectivityFullyDefined();
6578   int nbOfCells=getNumberOfCells();
6579   const int *conn=_nodal_connec->getConstPointer();
6580   const int *connI=_nodal_connec_index->getConstPointer();
6581   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6583   tmpa->alloc(nbOfCells,1);
6584   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6585   tmpb->fillWithZero();
6586   int *tmp=tmpa->getPointer();
6587   int *tmp2=tmpb->getPointer();
6588   for(const int *i=connI;i!=connI+nbOfCells;i++)
6589     {
6590       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6591       if(where!=orderEnd)
6592         {
6593           int pos=(int)std::distance(orderBg,where);
6594           tmp2[pos]++;
6595           tmp[std::distance(connI,i)]=pos;
6596         }
6597       else
6598         {
6599           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6600           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6601           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6602           throw INTERP_KERNEL::Exception(oss.str().c_str());
6603         }
6604     }
6605   nbPerType=tmpb.retn();
6606   return tmpa.retn();
6607 }
6608
6609 /*!
6610  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6611  *
6612  * \return a new object containing the old to new correspondance.
6613  *
6614  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6615  */
6616 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6617 {
6618   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6619 }
6620
6621 /*!
6622  * 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.
6623  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6624  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6625  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6626  */
6627 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6628 {
6629   DataArrayInt *nbPerType=0;
6630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6631   nbPerType->decrRef();
6632   return tmpa->buildPermArrPerLevel();
6633 }
6634
6635 /*!
6636  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6637  * The number of cells remains unchanged after the call of this method.
6638  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6639  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6640  *
6641  * \return the array giving the correspondance old to new.
6642  */
6643 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6644 {
6645   checkFullyDefined();
6646   computeTypes();
6647   const int *conn=_nodal_connec->getConstPointer();
6648   const int *connI=_nodal_connec_index->getConstPointer();
6649   int nbOfCells=getNumberOfCells();
6650   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6651   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6652     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6653       {
6654         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6655         types.push_back(curType);
6656         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6657       }
6658   DataArrayInt *ret=DataArrayInt::New();
6659   ret->alloc(nbOfCells,1);
6660   int *retPtr=ret->getPointer();
6661   std::fill(retPtr,retPtr+nbOfCells,-1);
6662   int newCellId=0;
6663   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6664     {
6665       for(const int *i=connI;i!=connI+nbOfCells;i++)
6666         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6667           retPtr[std::distance(connI,i)]=newCellId++;
6668     }
6669   renumberCells(retPtr,false);
6670   return ret;
6671 }
6672
6673 /*!
6674  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6675  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6676  * This method makes asumption that connectivity is correctly set before calling.
6677  */
6678 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6679 {
6680   checkFullyDefined();
6681   const int *conn=_nodal_connec->getConstPointer();
6682   const int *connI=_nodal_connec_index->getConstPointer();
6683   int nbOfCells=getNumberOfCells();
6684   std::vector<MEDCouplingUMesh *> ret;
6685   for(const int *i=connI;i!=connI+nbOfCells;)
6686     {
6687       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6688       int beginCellId=(int)std::distance(connI,i);
6689       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6690       int endCellId=(int)std::distance(connI,i);
6691       int sz=endCellId-beginCellId;
6692       int *cells=new int[sz];
6693       for(int j=0;j<sz;j++)
6694         cells[j]=beginCellId+j;
6695       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6696       delete [] cells;
6697       ret.push_back(m);
6698     }
6699   return ret;
6700 }
6701
6702 /*!
6703  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6704  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6705  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6706  *
6707  * \return a newly allocated instance, that the caller must manage.
6708  * \throw If \a this contains more than one geometric type.
6709  * \throw If the nodal connectivity of \a this is not fully defined.
6710  * \throw If the internal data is not coherent.
6711  */
6712 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6713 {
6714   checkConnectivityFullyDefined();
6715     if(_types.size()!=1)
6716     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6717   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6718   int typi=(int)typ;
6719   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6720   ret->setCoords(ret->getCoords());
6721   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6722   if(retC)
6723     {
6724       int nbCells=getNumberOfCells();
6725       int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6726       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6727       int *outPtr=connOut->getPointer();
6728       const int *conn=_nodal_connec->begin();
6729       const int *connI=_nodal_connec_index->begin();
6730       nbNodesPerCell++;
6731       for(int i=0;i<nbCells;i++,connI++)
6732         {
6733           if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6734             outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6735           else
6736             {
6737               std::ostringstream oss; oss << "MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : 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 << ") !";
6738               throw INTERP_KERNEL::Exception(oss.str().c_str());
6739             }
6740         }
6741       retC->setNodalConnectivity(connOut);
6742     }
6743   else
6744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6745   return ret.retn();
6746 }
6747
6748 /*!
6749  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6750  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6751  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6752  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6753  * are not used here to avoid the build of big permutation array.
6754  *
6755  * \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
6756  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6757  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6758  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6759  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6760  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6761  * \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
6762  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6763  */
6764 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6765                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6766                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6767 {
6768   std::vector<const MEDCouplingUMesh *> ms2;
6769   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6770     if(*it)
6771       {
6772         (*it)->checkConnectivityFullyDefined();
6773         ms2.push_back(*it);
6774       }
6775   if(ms2.empty())
6776     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6777   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6778   int meshDim=ms2[0]->getMeshDimension();
6779   std::vector<const MEDCouplingUMesh *> m1ssm;
6780   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6781   //
6782   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6783   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6784   int fake=0,rk=0;
6785   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6786   ret1->alloc(0,1); ret2->alloc(0,1);
6787   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6788     {
6789       if(meshDim!=(*it)->getMeshDimension())
6790         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6791       if(refCoo!=(*it)->getCoords())
6792         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6793       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6794       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6795       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6796       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6797         {
6798           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6799           m1ssmSingleAuto.push_back(singleCell);
6800           m1ssmSingle.push_back(singleCell);
6801           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6802         }
6803     }
6804   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6806   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6807   for(std::size_t i=0;i<m1ssm.size();i++)
6808     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6809   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6810   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6811   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6812   return ret0.retn();
6813 }
6814
6815 /*!
6816  * This method returns a newly created DataArrayInt instance.
6817  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6818  */
6819 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6820 {
6821   checkFullyDefined();
6822   const int *conn=_nodal_connec->getConstPointer();
6823   const int *connIndex=_nodal_connec_index->getConstPointer();
6824   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6825   for(const int *w=begin;w!=end;w++)
6826     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6827       ret->pushBackSilent(*w);
6828   return ret.retn();
6829 }
6830
6831 /*!
6832  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6833  * are in [0:getNumberOfCells())
6834  */
6835 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6836 {
6837   checkFullyDefined();
6838   const int *conn=_nodal_connec->getConstPointer();
6839   const int *connI=_nodal_connec_index->getConstPointer();
6840   int nbOfCells=getNumberOfCells();
6841   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6842   int *tmp=new int[nbOfCells];
6843   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6844     {
6845       int j=0;
6846       for(const int *i=connI;i!=connI+nbOfCells;i++)
6847         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6848           tmp[std::distance(connI,i)]=j++;
6849     }
6850   DataArrayInt *ret=DataArrayInt::New();
6851   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6852   ret->copyStringInfoFrom(*da);
6853   int *retPtr=ret->getPointer();
6854   const int *daPtr=da->getConstPointer();
6855   int nbOfElems=da->getNbOfElems();
6856   for(int k=0;k<nbOfElems;k++)
6857     retPtr[k]=tmp[daPtr[k]];
6858   delete [] tmp;
6859   return ret;
6860 }
6861
6862 /*!
6863  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6864  * This method \b works \b for mesh sorted by type.
6865  * cells whose ids is in 'idsPerGeoType' array.
6866  * This method conserves coords and name of mesh.
6867  */
6868 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6869 {
6870   std::vector<int> code=getDistributionOfTypes();
6871   std::size_t nOfTypesInThis=code.size()/3;
6872   int sz=0,szOfType=0;
6873   for(std::size_t i=0;i<nOfTypesInThis;i++)
6874     {
6875       if(code[3*i]!=type)
6876         sz+=code[3*i+1];
6877       else
6878         szOfType=code[3*i+1];
6879     }
6880   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6881     if(*work<0 || *work>=szOfType)
6882       {
6883         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6884         oss << ". It should be in [0," << szOfType << ") !";
6885         throw INTERP_KERNEL::Exception(oss.str().c_str());
6886       }
6887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6888   int *idsPtr=idsTokeep->getPointer();
6889   int offset=0;
6890   for(std::size_t i=0;i<nOfTypesInThis;i++)
6891     {
6892       if(code[3*i]!=type)
6893         for(int j=0;j<code[3*i+1];j++)
6894           *idsPtr++=offset+j;
6895       else
6896         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6897       offset+=code[3*i+1];
6898     }
6899   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6900   ret->copyTinyInfoFrom(this);
6901   return ret.retn();
6902 }
6903
6904 /*!
6905  * This method returns a vector of size 'this->getNumberOfCells()'.
6906  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6907  */
6908 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6909 {
6910   int ncell=getNumberOfCells();
6911   std::vector<bool> ret(ncell);
6912   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6913   const int *c=getNodalConnectivity()->getConstPointer();
6914   for(int i=0;i<ncell;i++)
6915     {
6916       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6917       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6918       ret[i]=cm.isQuadratic();
6919     }
6920   return ret;
6921 }
6922
6923 /*!
6924  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6925  */
6926 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6927 {
6928   if(other->getType()!=UNSTRUCTURED)
6929     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6930   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6931   return MergeUMeshes(this,otherC);
6932 }
6933
6934 /*!
6935  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6936  * computed by averaging coordinates of cell nodes, so this method is not a right
6937  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6938  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6939  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6940  *          components. The caller is to delete this array using decrRef() as it is
6941  *          no more needed.
6942  *  \throw If the coordinates array is not set.
6943  *  \throw If the nodal connectivity of cells is not defined.
6944  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6945  */
6946 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6947 {
6948   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6949   int spaceDim=getSpaceDimension();
6950   int nbOfCells=getNumberOfCells();
6951   ret->alloc(nbOfCells,spaceDim);
6952   ret->copyStringInfoFrom(*getCoords());
6953   double *ptToFill=ret->getPointer();
6954   const int *nodal=_nodal_connec->getConstPointer();
6955   const int *nodalI=_nodal_connec_index->getConstPointer();
6956   const double *coor=_coords->getConstPointer();
6957   for(int i=0;i<nbOfCells;i++)
6958     {
6959       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6960       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6961       ptToFill+=spaceDim;
6962     }
6963   return ret.retn();
6964 }
6965
6966 /*!
6967  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6968  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
6969  * 
6970  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6971  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6972  * 
6973  * \sa MEDCouplingUMesh::getBarycenterAndOwner
6974  * \throw If \a this is not fully defined (coordinates and connectivity)
6975  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6976  */
6977 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
6978 {
6979   checkFullyDefined();
6980   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6981   int spaceDim=getSpaceDimension();
6982   int nbOfCells=getNumberOfCells();
6983   int nbOfNodes=getNumberOfNodes();
6984   ret->alloc(nbOfCells,spaceDim);
6985   double *ptToFill=ret->getPointer();
6986   const int *nodal=_nodal_connec->getConstPointer();
6987   const int *nodalI=_nodal_connec_index->getConstPointer();
6988   const double *coor=_coords->getConstPointer();
6989   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6990     {
6991       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6992       std::fill(ptToFill,ptToFill+spaceDim,0.);
6993       if(type!=INTERP_KERNEL::NORM_POLYHED)
6994         {
6995           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6996             {
6997               if(*conn>=0 && *conn<nbOfNodes)
6998                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6999               else
7000                 {
7001                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7002                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7003                 }
7004             }
7005           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7006           if(nbOfNodesInCell>0)
7007             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7008           else
7009             {
7010               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7011               throw INTERP_KERNEL::Exception(oss.str().c_str());
7012             }
7013         }
7014       else
7015         {
7016           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7017           s.erase(-1);
7018           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7019             {
7020               if(*it>=0 && *it<nbOfNodes)
7021                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7022               else
7023                 {
7024                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7025                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7026                 }
7027             }
7028           if(!s.empty())
7029             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7030           else
7031             {
7032               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7033               throw INTERP_KERNEL::Exception(oss.str().c_str());
7034             }
7035         }
7036     }
7037   return ret.retn();
7038 }
7039
7040 /*!
7041  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7042  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7043  * are specified via an array of cell ids. 
7044  *  \warning Validity of the specified cell ids is not checked! 
7045  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7046  *  \param [in] begin - an array of cell ids of interest.
7047  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7048  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7049  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7050  *          caller is to delete this array using decrRef() as it is no more needed. 
7051  *  \throw If the coordinates array is not set.
7052  *  \throw If the nodal connectivity of cells is not defined.
7053  *
7054  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7055  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7056  */
7057 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7058 {
7059   DataArrayDouble *ret=DataArrayDouble::New();
7060   int spaceDim=getSpaceDimension();
7061   int nbOfTuple=(int)std::distance(begin,end);
7062   ret->alloc(nbOfTuple,spaceDim);
7063   double *ptToFill=ret->getPointer();
7064   double *tmp=new double[spaceDim];
7065   const int *nodal=_nodal_connec->getConstPointer();
7066   const int *nodalI=_nodal_connec_index->getConstPointer();
7067   const double *coor=_coords->getConstPointer();
7068   for(const int *w=begin;w!=end;w++)
7069     {
7070       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7071       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7072       ptToFill+=spaceDim;
7073     }
7074   delete [] tmp;
7075   return ret;
7076 }
7077
7078 /*!
7079  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7080  * 
7081  */
7082 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7083 {
7084   if(!da)
7085     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7086   da->checkAllocated();
7087   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7088   ret->setCoords(da);
7089   int nbOfTuples=da->getNumberOfTuples();
7090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7091   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7092   c->alloc(2*nbOfTuples,1);
7093   cI->alloc(nbOfTuples+1,1);
7094   int *cp=c->getPointer();
7095   int *cip=cI->getPointer();
7096   *cip++=0;
7097   for(int i=0;i<nbOfTuples;i++)
7098     {
7099       *cp++=INTERP_KERNEL::NORM_POINT1;
7100       *cp++=i;
7101       *cip++=2*(i+1);
7102     }
7103   ret->setConnectivity(c,cI,true);
7104   return ret.retn();
7105 }
7106 /*!
7107  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7108  * Cells and nodes of
7109  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7110  *  \param [in] mesh1 - the first mesh.
7111  *  \param [in] mesh2 - the second mesh.
7112  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7113  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7114  *          is no more needed.
7115  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7116  *  \throw If the coordinates array is not set in none of the meshes.
7117  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7118  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7119  */
7120 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7121 {
7122   std::vector<const MEDCouplingUMesh *> tmp(2);
7123   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7124   return MergeUMeshes(tmp);
7125 }
7126
7127 /*!
7128  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7129  * Cells and nodes of
7130  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7131  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7132  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7133  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7134  *          is no more needed.
7135  *  \throw If \a a.size() == 0.
7136  *  \throw If \a a[ *i* ] == NULL.
7137  *  \throw If the coordinates array is not set in none of the meshes.
7138  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7139  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7140 */
7141 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7142 {
7143   std::size_t sz=a.size();
7144   if(sz==0)
7145     return MergeUMeshesLL(a);
7146   for(std::size_t ii=0;ii<sz;ii++)
7147     if(!a[ii])
7148       {
7149         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7150         throw INTERP_KERNEL::Exception(oss.str().c_str());
7151       }
7152   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7153   std::vector< const MEDCouplingUMesh * > aa(sz);
7154   int spaceDim=-3;
7155   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7156     {
7157       const MEDCouplingUMesh *cur=a[i];
7158       const DataArrayDouble *coo=cur->getCoords();
7159       if(coo)
7160         spaceDim=coo->getNumberOfComponents();
7161     }
7162   if(spaceDim==-3)
7163     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7164   for(std::size_t i=0;i<sz;i++)
7165     {
7166       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7167       aa[i]=bb[i];
7168     }
7169   return MergeUMeshesLL(aa);
7170 }
7171
7172 /// @cond INTERNAL
7173
7174 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7175 {
7176   if(a.empty())
7177     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7178   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7179   int meshDim=(*it)->getMeshDimension();
7180   int nbOfCells=(*it)->getNumberOfCells();
7181   int meshLgth=(*it++)->getMeshLength();
7182   for(;it!=a.end();it++)
7183     {
7184       if(meshDim!=(*it)->getMeshDimension())
7185         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7186       nbOfCells+=(*it)->getNumberOfCells();
7187       meshLgth+=(*it)->getMeshLength();
7188     }
7189   std::vector<const MEDCouplingPointSet *> aps(a.size());
7190   std::copy(a.begin(),a.end(),aps.begin());
7191   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7192   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7193   ret->setCoords(pts);
7194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7195   c->alloc(meshLgth,1);
7196   int *cPtr=c->getPointer();
7197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7198   cI->alloc(nbOfCells+1,1);
7199   int *cIPtr=cI->getPointer();
7200   *cIPtr++=0;
7201   int offset=0;
7202   int offset2=0;
7203   for(it=a.begin();it!=a.end();it++)
7204     {
7205       int curNbOfCell=(*it)->getNumberOfCells();
7206       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7207       const int *curC=(*it)->_nodal_connec->getConstPointer();
7208       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7209       for(int j=0;j<curNbOfCell;j++)
7210         {
7211           const int *src=curC+curCI[j];
7212           *cPtr++=*src++;
7213           for(;src!=curC+curCI[j+1];src++,cPtr++)
7214             {
7215               if(*src!=-1)
7216                 *cPtr=*src+offset2;
7217               else
7218                 *cPtr=-1;
7219             }
7220         }
7221       offset+=curCI[curNbOfCell];
7222       offset2+=(*it)->getNumberOfNodes();
7223     }
7224   //
7225   ret->setConnectivity(c,cI,true);
7226   return ret.retn();
7227 }
7228
7229 /// @endcond
7230
7231 /*!
7232  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7233  * dimension and sharing the node coordinates array.
7234  * All cells of the first mesh precede all cells of the second mesh
7235  * within the result mesh. 
7236  *  \param [in] mesh1 - the first mesh.
7237  *  \param [in] mesh2 - the second mesh.
7238  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7239  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7240  *          is no more needed.
7241  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7242  *  \throw If the meshes do not share the node coordinates array.
7243  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7244  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7245  */
7246 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7247 {
7248   std::vector<const MEDCouplingUMesh *> tmp(2);
7249   tmp[0]=mesh1; tmp[1]=mesh2;
7250   return MergeUMeshesOnSameCoords(tmp);
7251 }
7252
7253 /*!
7254  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7255  * dimension and sharing the node coordinates array.
7256  * All cells of the *i*-th mesh precede all cells of the
7257  * (*i*+1)-th mesh within the result mesh.
7258  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7259  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7260  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7261  *          is no more needed.
7262  *  \throw If \a a.size() == 0.
7263  *  \throw If \a a[ *i* ] == NULL.
7264  *  \throw If the meshes do not share the node coordinates array.
7265  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7266  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7267  */
7268 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7269 {
7270   if(meshes.empty())
7271     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7272   for(std::size_t ii=0;ii<meshes.size();ii++)
7273     if(!meshes[ii])
7274       {
7275         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7276         throw INTERP_KERNEL::Exception(oss.str().c_str());
7277       }
7278   const DataArrayDouble *coords=meshes.front()->getCoords();
7279   int meshDim=meshes.front()->getMeshDimension();
7280   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7281   int meshLgth=0;
7282   int meshIndexLgth=0;
7283   for(;iter!=meshes.end();iter++)
7284     {
7285       if(coords!=(*iter)->getCoords())
7286         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7287       if(meshDim!=(*iter)->getMeshDimension())
7288         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7289       meshLgth+=(*iter)->getMeshLength();
7290       meshIndexLgth+=(*iter)->getNumberOfCells();
7291     }
7292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7293   nodal->alloc(meshLgth,1);
7294   int *nodalPtr=nodal->getPointer();
7295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7296   nodalIndex->alloc(meshIndexLgth+1,1);
7297   int *nodalIndexPtr=nodalIndex->getPointer();
7298   int offset=0;
7299   for(iter=meshes.begin();iter!=meshes.end();iter++)
7300     {
7301       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7302       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7303       int nbOfCells=(*iter)->getNumberOfCells();
7304       int meshLgth2=(*iter)->getMeshLength();
7305       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7306       if(iter!=meshes.begin())
7307         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7308       else
7309         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7310       offset+=meshLgth2;
7311     }
7312   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7313   ret->setName("merge");
7314   ret->setMeshDimension(meshDim);
7315   ret->setConnectivity(nodal,nodalIndex,true);
7316   ret->setCoords(coords);
7317   return ret;
7318 }
7319
7320 /*!
7321  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7322  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7323  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7324  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7325  * New" mode are returned for each input mesh.
7326  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7327  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7328  *          valid values [0,1,2], see zipConnectivityTraducer().
7329  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7330  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7331  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7332  *          no more needed.
7333  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7334  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7335  *          is no more needed.
7336  *  \throw If \a meshes.size() == 0.
7337  *  \throw If \a meshes[ *i* ] == NULL.
7338  *  \throw If the meshes do not share the node coordinates array.
7339  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7340  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7341  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7342  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7343  */
7344 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7345 {
7346   //All checks are delegated to MergeUMeshesOnSameCoords
7347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7349   corr.resize(meshes.size());
7350   std::size_t nbOfMeshes=meshes.size();
7351   int offset=0;
7352   const int *o2nPtr=o2n->getConstPointer();
7353   for(std::size_t i=0;i<nbOfMeshes;i++)
7354     {
7355       DataArrayInt *tmp=DataArrayInt::New();
7356       int curNbOfCells=meshes[i]->getNumberOfCells();
7357       tmp->alloc(curNbOfCells,1);
7358       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7359       offset+=curNbOfCells;
7360       tmp->setName(meshes[i]->getName());
7361       corr[i]=tmp;
7362     }
7363   return ret.retn();
7364 }
7365
7366 /*!
7367  * Makes all given meshes share the nodal connectivity array. The common connectivity
7368  * array is created by concatenating the connectivity arrays of all given meshes. All
7369  * the given meshes must be of the same space dimension but dimension of cells **can
7370  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7371  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7372  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7373  *  \param [in,out] meshes - a vector of meshes to update.
7374  *  \throw If any of \a meshes is NULL.
7375  *  \throw If the coordinates array is not set in any of \a meshes.
7376  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7377  *  \throw If \a meshes are of different space dimension.
7378  */
7379 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7380 {
7381   std::size_t sz=meshes.size();
7382   if(sz==0 || sz==1)
7383     return;
7384   std::vector< const DataArrayDouble * > coords(meshes.size());
7385   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7386   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7387     {
7388       if((*it))
7389         {
7390           (*it)->checkConnectivityFullyDefined();
7391           const DataArrayDouble *coo=(*it)->getCoords();
7392           if(coo)
7393             *it2=coo;
7394           else
7395             {
7396               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7397               oss << " has no coordinate array defined !";
7398               throw INTERP_KERNEL::Exception(oss.str().c_str());
7399             }
7400         }
7401       else
7402         {
7403           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7404           oss << " is null !";
7405           throw INTERP_KERNEL::Exception(oss.str().c_str());
7406         }
7407     }
7408   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7409   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7410   int offset=(*it)->getNumberOfNodes();
7411   (*it++)->setCoords(res);
7412   for(;it!=meshes.end();it++)
7413     {
7414       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7415       (*it)->setCoords(res);
7416       (*it)->shiftNodeNumbersInConn(offset);
7417       offset+=oldNumberOfNodes;
7418     }
7419 }
7420
7421 /*!
7422  * Merges nodes coincident with a given precision within all given meshes that share
7423  * the nodal connectivity array. The given meshes **can be of different** mesh
7424  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7425  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7426  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7427  *  \param [in,out] meshes - a vector of meshes to update.
7428  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7429  *  \throw If any of \a meshes is NULL.
7430  *  \throw If the \a meshes do not share the same node coordinates array.
7431  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7432  */
7433 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7434 {
7435   if(meshes.empty())
7436     return ;
7437   std::set<const DataArrayDouble *> s;
7438   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7439     {
7440       if(*it)
7441         s.insert((*it)->getCoords());
7442       else
7443         {
7444           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 !";
7445           throw INTERP_KERNEL::Exception(oss.str().c_str());
7446         }
7447     }
7448   if(s.size()!=1)
7449     {
7450       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 !";
7451       throw INTERP_KERNEL::Exception(oss.str().c_str());
7452     }
7453   const DataArrayDouble *coo=*(s.begin());
7454   if(!coo)
7455     return;
7456   //
7457   DataArrayInt *comm,*commI;
7458   coo->findCommonTuples(eps,-1,comm,commI);
7459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7460   int oldNbOfNodes=coo->getNumberOfTuples();
7461   int newNbOfNodes;
7462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7463   if(oldNbOfNodes==newNbOfNodes)
7464     return ;
7465   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7466   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7467     {
7468       (*it)->renumberNodesInConn(o2n->getConstPointer());
7469       (*it)->setCoords(newCoords);
7470     } 
7471 }
7472
7473 /*!
7474  * 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.
7475  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7476  * \param isQuad specifies the policy of connectivity.
7477  * @ret in/out parameter in which the result will be append
7478  */
7479 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7480 {
7481   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7482   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7483   ret.push_back(cm.getExtrudedType());
7484   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7485   switch(flatType)
7486     {
7487     case INTERP_KERNEL::NORM_POINT1:
7488       {
7489         ret.push_back(connBg[1]);
7490         ret.push_back(connBg[1]+nbOfNodesPerLev);
7491         break;
7492       }
7493     case INTERP_KERNEL::NORM_SEG2:
7494       {
7495         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7496         ret.insert(ret.end(),conn,conn+4);
7497         break;
7498       }
7499     case INTERP_KERNEL::NORM_SEG3:
7500       {
7501         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7502         ret.insert(ret.end(),conn,conn+8);
7503         break;
7504       }
7505     case INTERP_KERNEL::NORM_QUAD4:
7506       {
7507         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7508         ret.insert(ret.end(),conn,conn+8);
7509         break;
7510       }
7511     case INTERP_KERNEL::NORM_TRI3:
7512       {
7513         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7514         ret.insert(ret.end(),conn,conn+6);
7515         break;
7516       }
7517     case INTERP_KERNEL::NORM_TRI6:
7518       {
7519         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,
7520                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7521         ret.insert(ret.end(),conn,conn+15);
7522         break;
7523       }
7524     case INTERP_KERNEL::NORM_QUAD8:
7525       {
7526         int conn[20]={
7527           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7528           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7529           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7530         };
7531         ret.insert(ret.end(),conn,conn+20);
7532         break;
7533       }
7534     case INTERP_KERNEL::NORM_POLYGON:
7535       {
7536         std::back_insert_iterator< std::vector<int> > ii(ret);
7537         std::copy(connBg+1,connEnd,ii);
7538         *ii++=-1;
7539         std::reverse_iterator<const int *> rConnBg(connEnd);
7540         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7541         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7542         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7543         for(std::size_t i=0;i<nbOfRadFaces;i++)
7544           {
7545             *ii++=-1;
7546             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7547             std::copy(conn,conn+4,ii);
7548           }
7549         break;
7550       }
7551     default:
7552       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7553     }
7554 }
7555
7556 /*!
7557  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7558  */
7559 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7560 {
7561   double v[3]={0.,0.,0.};
7562   std::size_t sz=std::distance(begin,end);
7563   if(isQuadratic)
7564     sz/=2;
7565   for(std::size_t i=0;i<sz;i++)
7566     {
7567       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];
7568       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7569       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7570     }
7571   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7572 }
7573
7574 /*!
7575  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7576  */
7577 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7578 {
7579   std::vector<std::pair<int,int> > edges;
7580   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7581   const int *bgFace=begin;
7582   for(std::size_t i=0;i<nbOfFaces;i++)
7583     {
7584       const int *endFace=std::find(bgFace+1,end,-1);
7585       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7586       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7587         {
7588           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7589           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7590             return false;
7591           edges.push_back(p1);
7592         }
7593       bgFace=endFace+1;
7594     }
7595   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7596 }
7597
7598 /*!
7599  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7600  */
7601 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7602 {
7603   double vec0[3],vec1[3];
7604   std::size_t sz=std::distance(begin,end);
7605   if(sz%2!=0)
7606     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7607   int nbOfNodes=(int)sz/2;
7608   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7609   const double *pt0=coords+3*begin[0];
7610   const double *pt1=coords+3*begin[nbOfNodes];
7611   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7612   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7613 }
7614
7615 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7616 {
7617   std::size_t sz=std::distance(begin,end);
7618   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7619   std::size_t nbOfNodes(sz/2);
7620   std::copy(begin,end,(int *)tmp);
7621   for(std::size_t j=1;j<nbOfNodes;j++)
7622     {
7623       begin[j]=tmp[nbOfNodes-j];
7624       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7625     }
7626 }
7627
7628 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7629 {
7630   std::size_t sz=std::distance(begin,end);
7631   if(sz!=4)
7632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7633   double vec0[3],vec1[3];
7634   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7635   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]; 
7636   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;
7637 }
7638
7639 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7640 {
7641   std::size_t sz=std::distance(begin,end);
7642   if(sz!=5)
7643     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7644   double vec0[3];
7645   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7646   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7647   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7648 }
7649
7650 /*!
7651  * 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 ) 
7652  * 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
7653  * a 2D space.
7654  *
7655  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7656  * \param [in] coords the coordinates with nb of components exactly equal to 3
7657  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7658  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7659  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7660  */
7661 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7662 {
7663   int nbFaces=std::count(begin+1,end,-1)+1;
7664   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7665   double *vPtr=v->getPointer();
7666   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7667   double *pPtr=p->getPointer();
7668   const int *stFaceConn=begin+1;
7669   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7670     {
7671       const int *endFaceConn=std::find(stFaceConn,end,-1);
7672       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7673       stFaceConn=endFaceConn+1;
7674     }
7675   pPtr=p->getPointer(); vPtr=v->getPointer();
7676   DataArrayInt *comm1=0,*commI1=0;
7677   v->findCommonTuples(eps,-1,comm1,commI1);
7678   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7679   const int *comm1Ptr=comm1->getConstPointer();
7680   const int *commI1Ptr=commI1->getConstPointer();
7681   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7682   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7683   //
7684   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7685   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7686   mm->finishInsertingCells();
7687   //
7688   for(int i=0;i<nbOfGrps1;i++)
7689     {
7690       int vecId=comm1Ptr[commI1Ptr[i]];
7691       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7692       DataArrayInt *comm2=0,*commI2=0;
7693       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7694       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7695       const int *comm2Ptr=comm2->getConstPointer();
7696       const int *commI2Ptr=commI2->getConstPointer();
7697       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7698       for(int j=0;j<nbOfGrps2;j++)
7699         {
7700           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7701             {
7702               res->insertAtTheEnd(begin,end);
7703               res->pushBackSilent(-1);
7704             }
7705           else
7706             {
7707               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7708               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7709               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7710               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7711               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7712               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7713               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7714               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7715               const int *idsNodePtr=idsNode->getConstPointer();
7716               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];
7717               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7718               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7719               if(std::abs(norm)>eps)
7720                 {
7721                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7722                   mm3->rotate(center,vec,angle);
7723                 }
7724               mm3->changeSpaceDimension(2);
7725               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7726               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7727               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7728               int nbOfCells=mm4->getNumberOfCells();
7729               for(int k=0;k<nbOfCells;k++)
7730                 {
7731                   int l=0;
7732                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7733                     res->pushBackSilent(idsNodePtr[*work]);
7734                   res->pushBackSilent(-1);
7735                 }
7736             }
7737         }
7738     }
7739   res->popBackSilent();
7740 }
7741
7742 /*!
7743  * 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
7744  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7745  * 
7746  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7747  * \param [in] coords coordinates expected to have 3 components.
7748  * \param [in] begin start of the nodal connectivity of the face.
7749  * \param [in] end end of the nodal connectivity (excluded) of the face.
7750  * \param [out] v the normalized vector of size 3
7751  * \param [out] p the pos of plane
7752  */
7753 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7754 {
7755   std::size_t nbPoints=std::distance(begin,end);
7756   if(nbPoints<3)
7757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7758   double vec[3]={0.,0.,0.};
7759   std::size_t j=0;
7760   bool refFound=false;
7761   for(;j<nbPoints-1 && !refFound;j++)
7762     {
7763       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7764       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7765       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7766       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7767       if(norm>eps)
7768         {
7769           refFound=true;
7770           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7771         }
7772     }
7773   for(std::size_t i=j;i<nbPoints-1;i++)
7774     {
7775       double curVec[3];
7776       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7777       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7778       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7779       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7780       if(norm<eps)
7781         continue;
7782       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7783       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];
7784       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7785       if(norm>eps)
7786         {
7787           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7788           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7789           return ;
7790         }
7791     }
7792   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7793 }
7794
7795 /*!
7796  * This method tries to obtain a well oriented polyhedron.
7797  * If the algorithm fails, an exception will be thrown.
7798  */
7799 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7800 {
7801   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7802   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7803   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7804   isPerm[0]=true;
7805   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7806   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7807   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7808   //
7809   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7810     {
7811       bgFace=begin;
7812       std::size_t smthChanged=0;
7813       for(std::size_t i=0;i<nbOfFaces;i++)
7814         {
7815           endFace=std::find(bgFace+1,end,-1);
7816           nbOfEdgesInFace=std::distance(bgFace,endFace);
7817           if(!isPerm[i])
7818             {
7819               bool b;
7820               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7821                 {
7822                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7823                   std::pair<int,int> p2(p1.second,p1.first);
7824                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7825                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7826                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7827                 }
7828               if(isPerm[i])
7829                 { 
7830                   if(!b)
7831                     std::reverse(bgFace+1,endFace);
7832                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7833                     {
7834                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7835                       std::pair<int,int> p2(p1.second,p1.first);
7836                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7837                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7838                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7839                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7840                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7841                       if(it!=edgesOK.end())
7842                         {
7843                           edgesOK.erase(it);
7844                           edgesFinished.push_back(p1);
7845                         }
7846                       else
7847                         edgesOK.push_back(p1);
7848                     }
7849                 }
7850             }
7851           bgFace=endFace+1;
7852         }
7853       if(smthChanged==0)
7854         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7855     }
7856   if(!edgesOK.empty())
7857     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7858   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7859     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7860       bgFace=begin;
7861       for(std::size_t i=0;i<nbOfFaces;i++)
7862         {
7863           endFace=std::find(bgFace+1,end,-1);
7864           std::reverse(bgFace+1,endFace);
7865           bgFace=endFace+1;
7866         }
7867     }
7868 }
7869
7870 /*!
7871  * This method makes the assumption spacedimension == meshdimension == 2.
7872  * This method works only for linear cells.
7873  * 
7874  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7875  */
7876 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7877 {
7878   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7880   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7882   int nbOfNodesExpected=m->getNumberOfNodes();
7883   if(m->getNumberOfCells()!=nbOfNodesExpected)
7884     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7886   const int *n2oPtr=n2o->getConstPointer();
7887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7888   m->getReverseNodalConnectivity(revNodal,revNodalI);
7889   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7890   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7891   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7893   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7894   if(nbOfNodesExpected<1)
7895     return ret.retn();
7896   int prevCell=0;
7897   int prevNode=nodalPtr[nodalIPtr[0]+1];
7898   *work++=n2oPtr[prevNode];
7899   for(int i=1;i<nbOfNodesExpected;i++)
7900     {
7901       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7902         {
7903           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7904           conn.erase(prevNode);
7905           if(conn.size()==1)
7906             {
7907               int curNode=*(conn.begin());
7908               *work++=n2oPtr[curNode];
7909               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7910               shar.erase(prevCell);
7911               if(shar.size()==1)
7912                 {
7913                   prevCell=*(shar.begin());
7914                   prevNode=curNode;
7915                 }
7916               else
7917                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7918             }
7919           else
7920             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7921         }
7922       else
7923         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7924     }
7925   return ret.retn();
7926 }
7927
7928 /*!
7929  * This method makes the assumption spacedimension == meshdimension == 3.
7930  * This method works only for linear cells.
7931  * 
7932  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7933  */
7934 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7935 {
7936   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7938   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7939   const int *conn=m->getNodalConnectivity()->getConstPointer();
7940   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7941   int nbOfCells=m->getNumberOfCells();
7942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7943   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7944   if(nbOfCells<1)
7945     return ret.retn();
7946   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7947   for(int i=1;i<nbOfCells;i++)
7948     {
7949       *work++=-1;
7950       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7951     }
7952   return ret.retn();
7953 }
7954
7955 /*!
7956  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7957  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7958  */
7959 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7960 {
7961   double *w=zipFrmt;
7962   if(spaceDim==3)
7963     for(int i=0;i<nbOfNodesInCell;i++)
7964       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7965   else if(spaceDim==2)
7966     {
7967       for(int i=0;i<nbOfNodesInCell;i++)
7968         {
7969           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7970           *w++=0.;
7971         }
7972     }
7973   else
7974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7975 }
7976
7977 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7978 {
7979   int nbOfCells=getNumberOfCells();
7980   if(nbOfCells<=0)
7981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7982   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,-1,4};
7983   ofs << "  <" << getVTKDataSetType() << ">\n";
7984   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7985   ofs << "      <PointData>\n" << pointData << std::endl;
7986   ofs << "      </PointData>\n";
7987   ofs << "      <CellData>\n" << cellData << std::endl;
7988   ofs << "      </CellData>\n";
7989   ofs << "      <Points>\n";
7990   if(getSpaceDimension()==3)
7991     _coords->writeVTK(ofs,8,"Points");
7992   else
7993     {
7994       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7995       coo->writeVTK(ofs,8,"Points");
7996     }
7997   ofs << "      </Points>\n";
7998   ofs << "      <Cells>\n";
7999   const int *cPtr=_nodal_connec->getConstPointer();
8000   const int *cIPtr=_nodal_connec_index->getConstPointer();
8001   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8003   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8004   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8005   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8006   int szFaceOffsets=0,szConn=0;
8007   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8008     {
8009       *w2=cPtr[cIPtr[i]];
8010       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8011         {
8012           *w1=-1;
8013           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8014           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8015         }
8016       else
8017         {
8018           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8019           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8020           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8021           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8022           w4=std::copy(c.begin(),c.end(),w4);
8023         }
8024     }
8025   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8026   types->writeVTK(ofs,8,"UInt8","types");
8027   offsets->writeVTK(ofs,8,"Int32","offsets");
8028   if(szFaceOffsets!=0)
8029     {//presence of Polyhedra
8030       connectivity->reAlloc(szConn);
8031       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8032       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8033       w1=faces->getPointer();
8034       for(int i=0;i<nbOfCells;i++)
8035         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8036           {
8037             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8038             *w1++=nbFaces;
8039             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8040             for(int j=0;j<nbFaces;j++)
8041               {
8042                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8043                 *w1++=(int)std::distance(w6,w5);
8044                 w1=std::copy(w6,w5,w1);
8045                 w6=w5+1;
8046               }
8047           }
8048       faces->writeVTK(ofs,8,"Int32","faces");
8049     }
8050   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8051   ofs << "      </Cells>\n";
8052   ofs << "    </Piece>\n";
8053   ofs << "  </" << getVTKDataSetType() << ">\n";
8054 }
8055
8056 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8057 {
8058   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8059   if(_mesh_dim==-2)
8060     { stream << " Not set !"; return ; }
8061   stream << " Mesh dimension : " << _mesh_dim << ".";
8062   if(_mesh_dim==-1)
8063     return ;
8064   if(!_coords)
8065     { stream << " No coordinates set !"; return ; }
8066   if(!_coords->isAllocated())
8067     { stream << " Coordinates set but not allocated !"; return ; }
8068   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8069   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8070   if(!_nodal_connec_index)
8071     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8072   if(!_nodal_connec_index->isAllocated())
8073     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8074   int lgth=_nodal_connec_index->getNumberOfTuples();
8075   int cpt=_nodal_connec_index->getNumberOfComponents();
8076   if(cpt!=1 || lgth<1)
8077     return ;
8078   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8079 }
8080
8081 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8082 {
8083   return std::string("UnstructuredGrid");
8084 }
8085
8086 /*!
8087  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8088  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8089  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8090  * meshes.
8091  *  \param [in] m1 - the first input mesh which is a partitioned object.
8092  *  \param [in] m2 - the second input mesh which is a partition tool.
8093  *  \param [in] eps - precision used to detect coincident mesh entities.
8094  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8095  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8096  *         this array using decrRef() as it is no more needed.
8097  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8098  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8099  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8100  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8101  *         it is no more needed.  
8102  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8103  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8104  *         is no more needed.  
8105  *  \throw If the coordinates array is not set in any of the meshes.
8106  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8107  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8108  */
8109 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8110 {
8111   m1->checkFullyDefined();
8112   m2->checkFullyDefined();
8113   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8115   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8116   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8117   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8118   std::vector<double> addCoo,addCoordsQuadratic;
8119   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8120   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8121   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8122                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8123   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8125   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8126   std::vector< std::vector<int> > intersectEdge2;
8127   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8128   subDiv2.clear(); dd5=0; dd6=0;
8129   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8130   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8131   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8132                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8133   //
8134   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8135   addCooDa->alloc((int)(addCoo.size())/2,2);
8136   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8137   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8138   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8139   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8140   std::vector<const DataArrayDouble *> coordss(4);
8141   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8142   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8143   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8148   ret->setConnectivity(conn,connI,true);
8149   ret->setCoords(coo);
8150   cellNb1=c1.retn(); cellNb2=c2.retn();
8151   return ret.retn();
8152 }
8153
8154 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8155                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8156                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8157                                                          const std::vector<double>& addCoords,
8158                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8159 {
8160   static const int SPACEDIM=2;
8161   std::vector<double> bbox1,bbox2;
8162   const double *coo1=m1->getCoords()->getConstPointer();
8163   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8164   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8165   int offset1=m1->getNumberOfNodes();
8166   const double *coo2=m2->getCoords()->getConstPointer();
8167   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8168   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8169   int offset2=offset1+m2->getNumberOfNodes();
8170   int offset3=offset2+((int)addCoords.size())/2;
8171   m1->getBoundingBoxForBBTree(bbox1);
8172   m2->getBoundingBoxForBBTree(bbox2);
8173   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8174   int ncell1=m1->getNumberOfCells();
8175   crI.push_back(0);
8176   for(int i=0;i<ncell1;i++)
8177     {
8178       std::vector<int> candidates2;
8179       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8180       std::map<INTERP_KERNEL::Node *,int> mapp;
8181       std::map<int,INTERP_KERNEL::Node *> mappRev;
8182       INTERP_KERNEL::QuadraticPolygon pol1;
8183       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8184       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8185       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8186       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8187                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8188       //
8189       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
8190       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8191       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8192       for(it1.first();!it1.finished();it1.next())
8193         edges1.insert(it1.current()->getPtr());
8194       //
8195       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8196       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8197       int ii=0;
8198       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8199         {
8200           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8201           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8202           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8203           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8204                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8205         }
8206       ii=0;
8207       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8208         {
8209           pol1.initLocationsWithOther(pol2s[ii]);
8210           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8211           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8212           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8213         }
8214       if(!edges1.empty())
8215         {
8216           try
8217             {
8218               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8219             }
8220           catch(INTERP_KERNEL::Exception& e)
8221             {
8222               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();
8223               throw INTERP_KERNEL::Exception(oss.str().c_str());
8224             }
8225         }
8226       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8227         (*it).second->decrRef();
8228     }
8229 }
8230
8231 /*!
8232  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8233  * 
8234  */
8235 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8236                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8237                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8238                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8239                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8240 {
8241   static const int SPACEDIM=2;
8242   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8243   desc2=DataArrayInt::New();
8244   descIndx2=DataArrayInt::New();
8245   revDesc2=DataArrayInt::New();
8246   revDescIndx2=DataArrayInt::New();
8247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8249   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8250   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8251   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8252   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8253   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8254   std::vector<double> bbox1,bbox2;
8255   m1Desc->getBoundingBoxForBBTree(bbox1);
8256   m2Desc->getBoundingBoxForBBTree(bbox2);
8257   int ncell1=m1Desc->getNumberOfCells();
8258   int ncell2=m2Desc->getNumberOfCells();
8259   intersectEdge1.resize(ncell1);
8260   colinear2.resize(ncell2);
8261   subDiv2.resize(ncell2);
8262   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8263   std::vector<int> candidates1(1);
8264   int offset1=m1->getNumberOfNodes();
8265   int offset2=offset1+m2->getNumberOfNodes();
8266   for(int i=0;i<ncell1;i++)
8267     {
8268       std::vector<int> candidates2;
8269       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8270       if(!candidates2.empty())
8271         {
8272           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8273           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8274           candidates1[0]=i;
8275           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8276           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8277           delete pol2;
8278           delete pol1;
8279         }
8280       else
8281         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8282     }
8283   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8284   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8285 }
8286
8287 /*!
8288  * This method performs the 2nd step of Partition of 2D mesh.
8289  * This method has 4 inputs :
8290  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8291  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8292  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8293  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8294  * \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. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8295  * \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.
8296  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8297  */
8298 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8299 {
8300   int offset1=m1->getNumberOfNodes();
8301   int ncell=m2->getNumberOfCells();
8302   const int *c=m2->getNodalConnectivity()->getConstPointer();
8303   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8304   const double *coo=m2->getCoords()->getConstPointer();
8305   const double *cooBis=m1->getCoords()->getConstPointer();
8306   int offset2=offset1+m2->getNumberOfNodes();
8307   intersectEdge.resize(ncell);
8308   for(int i=0;i<ncell;i++,cI++)
8309     {
8310       const std::vector<int>& divs=subDiv[i];
8311       int nnode=cI[1]-cI[0]-1;
8312       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8313       std::map<INTERP_KERNEL::Node *, int> mapp22;
8314       for(int j=0;j<nnode;j++)
8315         {
8316           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8317           int nnid=c[(*cI)+j+1];
8318           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8319           mapp22[nn]=nnid+offset1;
8320         }
8321       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8322       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8323         ((*it).second.first)->decrRef();
8324       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8325       std::map<INTERP_KERNEL::Node *,int> mapp3;
8326       for(std::size_t j=0;j<divs.size();j++)
8327         {
8328           int id=divs[j];
8329           INTERP_KERNEL::Node *tmp=0;
8330           if(id<offset1)
8331             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8332           else if(id<offset2)
8333             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8334           else
8335             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8336           addNodes[j]=tmp;
8337           mapp3[tmp]=id;
8338         }
8339       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8340       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8341         (*it)->decrRef();
8342       e->decrRef();
8343     }
8344 }
8345
8346 /*!
8347  * 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).
8348  * 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
8349  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8350  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8351  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8352  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8353  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8354  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8355  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8356  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8357  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8358  * \param [out] cut3DSuf input/output param.
8359  */
8360 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8361                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8362                                                    const int *desc, const int *descIndx, 
8363                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8364 {
8365   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8366   int nbOf3DSurfCell=(int)cut3DSurf.size();
8367   for(int i=0;i<nbOf3DSurfCell;i++)
8368     {
8369       std::vector<int> res;
8370       int offset=descIndx[i];
8371       int nbOfSeg=descIndx[i+1]-offset;
8372       for(int j=0;j<nbOfSeg;j++)
8373         {
8374           int edgeId=desc[offset+j];
8375           int status=cut3DCurve[edgeId];
8376           if(status!=-2)
8377             {
8378               if(status>-1)
8379                 res.push_back(status);
8380               else
8381                 {
8382                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8383                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8384                 }
8385             }
8386         }
8387       switch(res.size())
8388         {
8389         case 2:
8390           {
8391             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8392             break;
8393           }
8394         case 1:
8395         case 0:
8396           {
8397             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8398             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8399             if(res.size()==2)
8400               {
8401                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8402               }
8403             else
8404               {
8405                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8406               }
8407             break;
8408           }
8409         default:
8410           {// case when plane is on a multi colinear edge of a polyhedron
8411             if((int)res.size()==2*nbOfSeg)
8412               {
8413                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8414               }
8415             else
8416               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8417           }
8418         }
8419     }
8420 }
8421
8422 /*!
8423  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8424  * 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).
8425  * 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
8426  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8427  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8428  * \param desc is the descending connectivity 3D->3DSurf
8429  * \param descIndx is the descending connectivity index 3D->3DSurf
8430  */
8431 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8432                                                   const int *desc, const int *descIndx,
8433                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8434 {
8435   checkFullyDefined();
8436   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8437     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8438   const int *nodal3D=_nodal_connec->getConstPointer();
8439   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8440   int nbOfCells=getNumberOfCells();
8441   for(int i=0;i<nbOfCells;i++)
8442     {
8443       std::map<int, std::set<int> > m;
8444       int offset=descIndx[i];
8445       int nbOfFaces=descIndx[i+1]-offset;
8446       int start=-1;
8447       int end=-1;
8448       for(int j=0;j<nbOfFaces;j++)
8449         {
8450           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8451           if(p.first!=-1 && p.second!=-1)
8452             {
8453               if(p.first!=-2)
8454                 {
8455                   start=p.first; end=p.second;
8456                   m[p.first].insert(p.second);
8457                   m[p.second].insert(p.first);
8458                 }
8459               else
8460                 {
8461                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8462                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8463                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8464                   INTERP_KERNEL::NormalizedCellType cmsId;
8465                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8466                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8467                   for(unsigned k=0;k<nbOfNodesSon;k++)
8468                     {
8469                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8470                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8471                     }
8472                 }
8473             }
8474         }
8475       if(m.empty())
8476         continue;
8477       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8478       int prev=end;
8479       while(end!=start)
8480         {
8481           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8482           const std::set<int>& s=(*it).second;
8483           std::set<int> s2; s2.insert(prev);
8484           std::set<int> s3;
8485           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8486           if(s3.size()==1)
8487             {
8488               int val=*s3.begin();
8489               conn.push_back(start);
8490               prev=start;
8491               start=val;
8492             }
8493           else
8494             start=end;
8495         }
8496       conn.push_back(end);
8497       if(conn.size()>3)
8498         {
8499           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8500           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8501           cellIds->pushBackSilent(i);
8502         }
8503     }
8504 }
8505
8506 /*!
8507  * 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
8508  * 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
8509  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8510  * 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
8511  * 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.
8512  * 
8513  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8514  */
8515 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8516 {
8517   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8518   if(sz>=4)
8519     {
8520       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8521       if(cm.getDimension()==2)
8522         {
8523           const int *node=nodalConnBg+1;
8524           int startNode=*node++;
8525           double refX=coords[2*startNode];
8526           for(;node!=nodalConnEnd;node++)
8527             {
8528               if(coords[2*(*node)]<refX)
8529                 {
8530                   startNode=*node;
8531                   refX=coords[2*startNode];
8532                 }
8533             }
8534           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8535           refX=1e300;
8536           double tmp1;
8537           double tmp2[2];
8538           double angle0=-M_PI/2;
8539           //
8540           int nextNode=-1;
8541           int prevNode=-1;
8542           double resRef;
8543           double angleNext=0.;
8544           while(nextNode!=startNode)
8545             {
8546               nextNode=-1;
8547               resRef=1e300;
8548               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8549                 {
8550                   if(*node!=tmpOut.back() && *node!=prevNode)
8551                     {
8552                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8553                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8554                       double res;
8555                       if(angleM<=angle0)
8556                         res=angle0-angleM;
8557                       else
8558                         res=angle0-angleM+2.*M_PI;
8559                       if(res<resRef)
8560                         {
8561                           nextNode=*node;
8562                           resRef=res;
8563                           angleNext=angleM;
8564                         }
8565                     }
8566                 }
8567               if(nextNode!=startNode)
8568                 {
8569                   angle0=angleNext-M_PI;
8570                   if(angle0<-M_PI)
8571                     angle0+=2*M_PI;
8572                   prevNode=tmpOut.back();
8573                   tmpOut.push_back(nextNode);
8574                 }
8575             }
8576           std::vector<int> tmp3(2*(sz-1));
8577           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8578           std::copy(nodalConnBg+1,nodalConnEnd,it);
8579           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8580             {
8581               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8582               return false;
8583             }
8584           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8585             {
8586               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8587               return false;
8588             }
8589           else
8590             {
8591               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8592               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8593               return true;
8594             }
8595         }
8596       else
8597         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8598     }
8599   else
8600     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8601 }
8602
8603 /*!
8604  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8605  * 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.
8606  * 
8607  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8608  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8609  * \param [in,out] arr array in which the remove operation will be done.
8610  * \param [in,out] arrIndx array in the remove operation will modify
8611  * \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])
8612  * \return true if \b arr and \b arrIndx have been modified, false if not.
8613  */
8614 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8615 {
8616   if(!arrIndx || !arr)
8617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8618   if(offsetForRemoval<0)
8619     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8620   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8621   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8622   int *arrIPtr=arrIndx->getPointer();
8623   *arrIPtr++=0;
8624   int previousArrI=0;
8625   const int *arrPtr=arr->getConstPointer();
8626   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8627   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8628     {
8629       if(*arrIPtr-previousArrI>offsetForRemoval)
8630         {
8631           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8632             {
8633               if(s.find(*work)==s.end())
8634                 arrOut.push_back(*work);
8635             }
8636         }
8637       previousArrI=*arrIPtr;
8638       *arrIPtr=(int)arrOut.size();
8639     }
8640   if(arr->getNumberOfTuples()==(int)arrOut.size())
8641     return false;
8642   arr->alloc((int)arrOut.size(),1);
8643   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8644   return true;
8645 }
8646
8647 /*!
8648  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8649  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8650  * The selection of extraction is done standardly in new2old format.
8651  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8652  *
8653  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8654  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8655  * \param [in] arrIn arr origin array from which the extraction will be done.
8656  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8657  * \param [out] arrOut the resulting array
8658  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8659  */
8660 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8661                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8662 {
8663   if(!arrIn || !arrIndxIn)
8664     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8665   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8666   const int *arrInPtr=arrIn->getConstPointer();
8667   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8668   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8669   int maxSizeOfArr=arrIn->getNumberOfTuples();
8670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8671   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8672   arrIo->alloc((int)(sz+1),1);
8673   const int *idsIt=idsOfSelectBg;
8674   int *work=arrIo->getPointer();
8675   *work++=0;
8676   int lgth=0;
8677   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8678     {
8679       if(*idsIt>=0 && *idsIt<nbOfGrps)
8680         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8681       else
8682         {
8683           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8684           throw INTERP_KERNEL::Exception(oss.str().c_str());
8685         }
8686       if(lgth>=work[-1])
8687         *work=lgth;
8688       else
8689         {
8690           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8691           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8692           throw INTERP_KERNEL::Exception(oss.str().c_str());
8693         }
8694     }
8695   arro->alloc(lgth,1);
8696   work=arro->getPointer();
8697   idsIt=idsOfSelectBg;
8698   for(std::size_t i=0;i<sz;i++,idsIt++)
8699     {
8700       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8701         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8702       else
8703         {
8704           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8705           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8706           throw INTERP_KERNEL::Exception(oss.str().c_str());
8707         }
8708     }
8709   arrOut=arro.retn();
8710   arrIndexOut=arrIo.retn();
8711 }
8712
8713 /*!
8714  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8715  * 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
8716  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8717  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8718  *
8719  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8720  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8721  * \param [in] arrIn arr origin array from which the extraction will be done.
8722  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8723  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8724  * \param [in] srcArrIndex index array of \b srcArr
8725  * \param [out] arrOut the resulting array
8726  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8727  * 
8728  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8729  */
8730 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8731                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8732                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8733 {
8734   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8736   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8738   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8739   std::vector<bool> v(nbOfTuples,true);
8740   int offset=0;
8741   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8742   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8743   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8744     {
8745       if(*it>=0 && *it<nbOfTuples)
8746         {
8747           v[*it]=false;
8748           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8749         }
8750       else
8751         {
8752           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8753           throw INTERP_KERNEL::Exception(oss.str().c_str());
8754         }
8755     }
8756   srcArrIndexPtr=srcArrIndex->getConstPointer();
8757   arrIo->alloc(nbOfTuples+1,1);
8758   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8759   const int *arrInPtr=arrIn->getConstPointer();
8760   const int *srcArrPtr=srcArr->getConstPointer();
8761   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8762   int *arroPtr=arro->getPointer();
8763   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8764     {
8765       if(v[ii])
8766         {
8767           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8768           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8769         }
8770       else
8771         {
8772           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8773           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8774           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8775         }
8776     }
8777   arrOut=arro.retn();
8778   arrIndexOut=arrIo.retn();
8779 }
8780
8781 /*!
8782  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8783  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8784  *
8785  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8786  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8787  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8788  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8789  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8790  * \param [in] srcArrIndex index array of \b srcArr
8791  * 
8792  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8793  */
8794 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8795                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8796 {
8797   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8799   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8800   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8801   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8802   int *arrInOutPtr=arrInOut->getPointer();
8803   const int *srcArrPtr=srcArr->getConstPointer();
8804   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8805     {
8806       if(*it>=0 && *it<nbOfTuples)
8807         {
8808           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8809             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8810           else
8811             {
8812               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] !";
8813               throw INTERP_KERNEL::Exception(oss.str().c_str());
8814             }
8815         }
8816       else
8817         {
8818           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8819           throw INTERP_KERNEL::Exception(oss.str().c_str());
8820         }
8821     }
8822 }
8823
8824 /*!
8825  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8826  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8827  * 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]].
8828  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8829  * A negative value in \b arrIn means that it is ignored.
8830  * 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.
8831  * 
8832  * \param [in] arrIn arr origin array from which the extraction will be done.
8833  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8834  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8835  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8836  */
8837 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8838 {
8839   int seed=0,nbOfDepthPeelingPerformed=0;
8840   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8841 }
8842
8843 /*!
8844  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8845  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8846  * 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]].
8847  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8848  * A negative value in \b arrIn means that it is ignored.
8849  * 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.
8850  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8851  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8852  * \param [in] arrIn arr origin array from which the extraction will be done.
8853  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8854  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8855  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8856  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8857  * \sa MEDCouplingUMesh::partitionBySpreadZone
8858  */
8859 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8860 {
8861   nbOfDepthPeelingPerformed=0;
8862   if(!arrIndxIn)
8863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8864   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8865   if(nbOfTuples<=0)
8866     {
8867       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8868       return ret;
8869     }
8870   //
8871   std::vector<bool> fetched(nbOfTuples,false);
8872   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8873 }
8874
8875 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8876 {
8877   nbOfDepthPeelingPerformed=0;
8878   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8880   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8881   std::vector<bool> fetched2(nbOfTuples,false);
8882   int i=0;
8883   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8884     {
8885       if(*seedElt>=0 && *seedElt<nbOfTuples)
8886         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8887       else
8888         { 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()); }
8889     }
8890   const int *arrInPtr=arrIn->getConstPointer();
8891   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8892   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8893   std::vector<int> idsToFetch1(seedBg,seedEnd);
8894   std::vector<int> idsToFetch2;
8895   std::vector<int> *idsToFetch=&idsToFetch1;
8896   std::vector<int> *idsToFetchOther=&idsToFetch2;
8897   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8898     {
8899       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8900         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8901           if(!fetched[*it2])
8902             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8903       std::swap(idsToFetch,idsToFetchOther);
8904       idsToFetchOther->clear();
8905       nbOfDepthPeelingPerformed++;
8906     }
8907   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8908   i=0;
8909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8910   int *retPtr=ret->getPointer();
8911   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8912     if(*it)
8913       *retPtr++=i;
8914   return ret.retn();
8915 }
8916
8917 /*!
8918  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8919  * 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
8920  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8921  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8922  *
8923  * \param [in] start begin of set of ids of the input extraction (included)
8924  * \param [in] end end of set of ids of the input extraction (excluded)
8925  * \param [in] step step of the set of ids in range mode.
8926  * \param [in] arrIn arr origin array from which the extraction will be done.
8927  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8928  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8929  * \param [in] srcArrIndex index array of \b srcArr
8930  * \param [out] arrOut the resulting array
8931  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8932  * 
8933  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8934  */
8935 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8936                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8937                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8938 {
8939   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8943   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8944   int offset=0;
8945   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8946   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8947   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8948   int it=start;
8949   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8950     {
8951       if(it>=0 && it<nbOfTuples)
8952         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8953       else
8954         {
8955           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8956           throw INTERP_KERNEL::Exception(oss.str().c_str());
8957         }
8958     }
8959   srcArrIndexPtr=srcArrIndex->getConstPointer();
8960   arrIo->alloc(nbOfTuples+1,1);
8961   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8962   const int *arrInPtr=arrIn->getConstPointer();
8963   const int *srcArrPtr=srcArr->getConstPointer();
8964   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8965   int *arroPtr=arro->getPointer();
8966   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8967     {
8968       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8969       if(pos<0)
8970         {
8971           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8972           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8973         }
8974       else
8975         {
8976           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8977           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8978         }
8979     }
8980   arrOut=arro.retn();
8981   arrIndexOut=arrIo.retn();
8982 }
8983
8984 /*!
8985  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8986  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8987  *
8988  * \param [in] start begin of set of ids of the input extraction (included)
8989  * \param [in] end end of set of ids of the input extraction (excluded)
8990  * \param [in] step step of the set of ids in range mode.
8991  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8992  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8993  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8994  * \param [in] srcArrIndex index array of \b srcArr
8995  * 
8996  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8997  */
8998 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8999                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9000 {
9001   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9003   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9004   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9005   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9006   int *arrInOutPtr=arrInOut->getPointer();
9007   const int *srcArrPtr=srcArr->getConstPointer();
9008   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9009   int it=start;
9010   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9011     {
9012       if(it>=0 && it<nbOfTuples)
9013         {
9014           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9015             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9016           else
9017             {
9018               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9019               throw INTERP_KERNEL::Exception(oss.str().c_str());
9020             }
9021         }
9022       else
9023         {
9024           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9025           throw INTERP_KERNEL::Exception(oss.str().c_str());
9026         }
9027     }
9028 }
9029
9030 /*!
9031  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9032  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9033  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9034  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9035  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9036  * 
9037  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9038  */
9039 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9040 {
9041   checkFullyDefined();
9042   int mdim=getMeshDimension();
9043   int spaceDim=getSpaceDimension();
9044   if(mdim!=spaceDim)
9045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9046   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9047   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9048   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9049   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9050   ret->setCoords(getCoords());
9051   ret->allocateCells((int)partition.size());
9052   //
9053   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9054     {
9055       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9056       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9057       switch(mdim)
9058         {
9059         case 2:
9060           cell=tmp->buildUnionOf2DMesh();
9061           break;
9062         case 3:
9063           cell=tmp->buildUnionOf3DMesh();
9064           break;
9065         default:
9066           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9067         }
9068       
9069       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9070     }
9071   //
9072   ret->finishInsertingCells();
9073   return ret.retn();
9074 }
9075
9076 /*!
9077  * This method partitions \b this into contiguous zone.
9078  * This method only needs a well defined connectivity. Coordinates are not considered here.
9079  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9080  */
9081 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9082 {
9083   //#if 0
9084   int nbOfCellsCur=getNumberOfCells();
9085   std::vector<DataArrayInt *> ret;
9086   if(nbOfCellsCur<=0)
9087     return ret;
9088   DataArrayInt *neigh=0,*neighI=0;
9089   computeNeighborsOfCells(neigh,neighI);
9090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9091   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9092   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9093   int seed=0;
9094   while(seed<nbOfCellsCur)
9095     {
9096       int nbOfPeelPerformed=0;
9097       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9098       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9099     }
9100   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9101     ret.push_back((*it).retn());
9102   return ret;
9103   //#endif
9104 #if 0
9105   int nbOfCellsCur=getNumberOfCells();
9106   DataArrayInt *neigh=0,*neighI=0;
9107   computeNeighborsOfCells(neigh,neighI);
9108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9109   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9110   std::vector<DataArrayInt *> ret;
9111   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9112   while(nbOfCellsCur>0)
9113     {
9114       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9115       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9116       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9117       ret2.push_back(tmp2);  ret.push_back(tmp2);
9118       nbOfCellsCur=tmp3->getNumberOfTuples();
9119       if(nbOfCellsCur>0)
9120         {
9121           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9122           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9123           neighAuto=neigh;
9124           neighIAuto=neighI;
9125           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9126           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9127         }
9128     }
9129   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9130     (*it)->incrRef();
9131   return ret;
9132 #endif
9133 }
9134
9135 /*!
9136  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9137  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9138  *
9139  * \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.
9140  * \return a newly allocated DataArrayInt to be managed by the caller.
9141  * \throw In case of \a code has not the right format (typically of size 3*n)
9142  */
9143 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9144 {
9145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9146   std::size_t nb=code.size()/3;
9147   if(code.size()%3!=0)
9148     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9149   ret->alloc((int)nb,2);
9150   int *retPtr=ret->getPointer();
9151   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9152     {
9153       retPtr[0]=code[3*i+2];
9154       retPtr[1]=code[3*i+2]+code[3*i+1];
9155     }
9156   return ret.retn();
9157 }
9158
9159 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9160                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9161 {
9162   if(mesh)
9163     {
9164       mesh->incrRef();
9165       _nb_cell=mesh->getNumberOfCells();
9166     }
9167 }
9168
9169 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9170 {
9171   if(_mesh)
9172     _mesh->decrRef();
9173   if(_own_cell)
9174     delete _cell;
9175 }
9176
9177 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9178                                                                                                                                _own_cell(false),_cell_id(bg-1),
9179                                                                                                                                _nb_cell(end)
9180 {
9181   if(mesh)
9182     mesh->incrRef();
9183 }
9184
9185 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9186 {
9187   _cell_id++;
9188   if(_cell_id<_nb_cell)
9189     {
9190       _cell->next();
9191       return _cell;
9192     }
9193   else
9194     return 0;
9195 }
9196
9197 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9198 {
9199   if(_mesh)
9200     _mesh->incrRef();
9201 }
9202
9203 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9204 {
9205   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9206 }
9207
9208 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9209 {
9210   if(_mesh)
9211     _mesh->decrRef();
9212 }
9213
9214 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9215                                                                                                                                                                   _itc(itc),
9216                                                                                                                                                                   _bg(bg),_end(end)
9217 {
9218   if(_mesh)
9219     _mesh->incrRef();
9220 }
9221
9222 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9223 {
9224   if(_mesh)
9225     _mesh->decrRef();
9226 }
9227
9228 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9229 {
9230   return _type;
9231 }
9232
9233 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9234 {
9235   return _end-_bg;
9236 }
9237
9238 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9239 {
9240   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9241 }
9242
9243 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9244 {
9245   if(mesh)
9246     {
9247       mesh->incrRef();
9248       _nb_cell=mesh->getNumberOfCells();
9249     }
9250 }
9251
9252 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9253 {
9254   if(_mesh)
9255     _mesh->decrRef();
9256   delete _cell;
9257 }
9258
9259 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9260 {
9261   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9262   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9263   if(_cell_id<_nb_cell)
9264     {
9265       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9266       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9267       int startId=_cell_id;
9268       _cell_id+=nbOfElems;
9269       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9270     }
9271   else
9272     return 0;
9273 }
9274
9275 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9276 {
9277   if(mesh)
9278     {
9279       _conn=mesh->getNodalConnectivity()->getPointer();
9280       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9281     }
9282 }
9283
9284 void MEDCouplingUMeshCell::next()
9285 {
9286   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9287     {
9288       _conn+=_conn_lgth;
9289       _conn_indx++;
9290     }
9291   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9292 }
9293
9294 std::string MEDCouplingUMeshCell::repr() const
9295 {
9296   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9297     {
9298       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9299       oss << " : ";
9300       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9301       return oss.str();
9302     }
9303   else
9304     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9305 }
9306
9307 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9308 {
9309   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9310     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9311   else
9312     return INTERP_KERNEL::NORM_ERROR;
9313 }
9314
9315 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9316 {
9317   lgth=_conn_lgth;
9318   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9319     return _conn;
9320   else
9321     return 0;
9322 }