Salome HOME
7053039d2e883fc8a9230a1b02793b410c20a98b
[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   return MEDCouplingPointSet::zipCoordsTraducer();
1438 }
1439
1440 /*!
1441  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1442  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1443  */
1444 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1445 {
1446   switch(compType)
1447     {
1448     case 0:
1449       return AreCellsEqual0(conn,connI,cell1,cell2);
1450     case 1:
1451       return AreCellsEqual1(conn,connI,cell1,cell2);
1452     case 2:
1453       return AreCellsEqual2(conn,connI,cell1,cell2);
1454     case 3:
1455       return AreCellsEqual3(conn,connI,cell1,cell2);
1456     case 7:
1457       return AreCellsEqual7(conn,connI,cell1,cell2);
1458     }
1459   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1460 }
1461
1462 /*!
1463  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1464  */
1465 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1466 {
1467   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1468     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1469   return 0;
1470 }
1471
1472 /*!
1473  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1474  */
1475 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1476 {
1477   int sz=connI[cell1+1]-connI[cell1];
1478   if(sz==connI[cell2+1]-connI[cell2])
1479     {
1480       if(conn[connI[cell1]]==conn[connI[cell2]])
1481         {
1482           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1483           unsigned dim=cm.getDimension();
1484           if(dim!=3)
1485             {
1486               if(dim!=1)
1487                 {
1488                   int sz1=2*(sz-1);
1489                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1490                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1491                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1492                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1493                   return work!=tmp+sz1?1:0;
1494                 }
1495               else
1496                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1497             }
1498           else
1499             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1500         }
1501     }
1502   return 0;
1503 }
1504
1505 /*!
1506  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1507  */
1508 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1509 {
1510   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1511     {
1512       if(conn[connI[cell1]]==conn[connI[cell2]])
1513         {
1514           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1515           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1516           return s1==s2?1:0;
1517         }
1518     }
1519   return 0;
1520 }
1521
1522 /*!
1523  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1524  */
1525 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1526 {
1527   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1528     {
1529       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1530       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1531       return s1==s2?1:0;
1532     }
1533   return 0;
1534 }
1535
1536 /*!
1537  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1538  */
1539 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1540 {
1541   int sz=connI[cell1+1]-connI[cell1];
1542   if(sz==connI[cell2+1]-connI[cell2])
1543     {
1544       if(conn[connI[cell1]]==conn[connI[cell2]])
1545         {
1546           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1547           unsigned dim=cm.getDimension();
1548           if(dim!=3)
1549             {
1550               if(dim!=1)
1551                 {
1552                   int sz1=2*(sz-1);
1553                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1554                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1555                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1556                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1557                   if(work!=tmp+sz1)
1558                     return 1;
1559                   else
1560                     {
1561                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1562                       std::reverse_iterator<int *> it2((int *)tmp);
1563                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1564                         return 2;
1565                       else
1566                         return 0;
1567                     }
1568                   
1569                   return work!=tmp+sz1?1:0;
1570                 }
1571               else
1572                 {//case of SEG2 and SEG3
1573                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1574                     return 1;
1575                   if(!cm.isQuadratic())
1576                     {
1577                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1578                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1579                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1580                         return 2;
1581                       return 0;
1582                     }
1583                   else
1584                     {
1585                       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])
1586                         return 2;
1587                       return 0;
1588                     }
1589                 }
1590             }
1591           else
1592             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1593         }
1594     }
1595   return 0;
1596 }
1597
1598 /*!
1599  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1600  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1601  * and result remains unchanged.
1602  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1603  * If in 'candidates' pool -1 value is considered as an empty value.
1604  * WARNING this method returns only ONE set of result !
1605  */
1606 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1607 {
1608   if(candidates.size()<1)
1609     return false;
1610   bool ret=false;
1611   std::vector<int>::const_iterator iter=candidates.begin();
1612   int start=(*iter++);
1613   for(;iter!=candidates.end();iter++)
1614     {
1615       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1616       if(status!=0)
1617         {
1618           if(!ret)
1619             {
1620               result->pushBackSilent(start);
1621               ret=true;
1622             }
1623           if(status==1)
1624             result->pushBackSilent(*iter);
1625           else
1626             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1627         }
1628     }
1629   return ret;
1630 }
1631
1632 /*!
1633  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1634  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1635  *
1636  * \param [in] compType input specifying the technique used to compare cells each other.
1637  *   - 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.
1638  *   - 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)
1639  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1640  *   - 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
1641  * can be used for users not sensitive to orientation of cell
1642  * \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.
1643  * \param [out] commonCells
1644  * \param [out] commonCellsI
1645  * \return the correspondance array old to new in a newly allocated array.
1646  * 
1647  */
1648 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1649 {
1650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1651   getReverseNodalConnectivity(revNodal,revNodalI);
1652   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1653 }
1654
1655 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1656                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1657 {
1658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1659   int nbOfCells=nodalI->getNumberOfTuples()-1;
1660   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1661   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1662   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1663   std::vector<bool> isFetched(nbOfCells,false);
1664   if(startCellId==0)
1665     {
1666       for(int i=0;i<nbOfCells;i++)
1667         {
1668           if(!isFetched[i])
1669             {
1670               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1671               std::vector<int> v,v2;
1672               if(connOfNode!=connPtr+connIPtr[i+1])
1673                 {
1674                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1675                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1676                   connOfNode++;
1677                 }
1678               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1679                 if(*connOfNode>=0)
1680                   {
1681                     v=v2;
1682                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1683                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1684                     v2.resize(std::distance(v2.begin(),it));
1685                   }
1686               if(v2.size()>1)
1687                 {
1688                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1689                     {
1690                       int pos=commonCellsI->back();
1691                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1692                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1693                         isFetched[*it]=true;
1694                     }
1695                 }
1696             }
1697         }
1698     }
1699   else
1700     {
1701       for(int i=startCellId;i<nbOfCells;i++)
1702         {
1703           if(!isFetched[i])
1704             {
1705               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1706               std::vector<int> v,v2;
1707               if(connOfNode!=connPtr+connIPtr[i+1])
1708                 {
1709                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1710                   connOfNode++;
1711                 }
1712               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1713                 if(*connOfNode>=0)
1714                   {
1715                     v=v2;
1716                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1717                     v2.resize(std::distance(v2.begin(),it));
1718                   }
1719               if(v2.size()>1)
1720                 {
1721                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1722                     {
1723                       int pos=commonCellsI->back();
1724                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1725                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1726                         isFetched[*it]=true;
1727                     }
1728                 }
1729             }
1730         }
1731     }
1732   commonCellsArr=commonCells.retn();
1733   commonCellsIArr=commonCellsI.retn();
1734 }
1735
1736 /*!
1737  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1738  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1739  * than \a other->getNumberOfCells() in the returned array means that there is no
1740  * corresponding cell in \a this mesh.
1741  * It is expected that \a this and \a other meshes share the same node coordinates
1742  * array, if it is not so an exception is thrown. 
1743  *  \param [in] other - the mesh to compare with.
1744  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1745  *         valid values [0,1,2], see zipConnectivityTraducer().
1746  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1747  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1748  *         values. The caller is to delete this array using
1749  *         decrRef() as it is no more needed.
1750  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1751  *         mesh.
1752  *
1753  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1754  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1755  *  \sa checkDeepEquivalOnSameNodesWith()
1756  *  \sa checkGeoEquivalWith()
1757  */
1758 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1759 {
1760   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1761   int nbOfCells=getNumberOfCells();
1762   static const int possibleCompType[]={0,1,2};
1763   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1764     {
1765       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1766       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1767       oss << " !";
1768       throw INTERP_KERNEL::Exception(oss.str().c_str());
1769     }
1770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1771   arr=o2n->substr(nbOfCells);
1772   arr->setName(other->getName());
1773   int tmp;
1774   if(other->getNumberOfCells()==0)
1775     return true;
1776   return arr->getMaxValue(tmp)<nbOfCells;
1777 }
1778
1779 /*!
1780  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1781  * This method tries to determine if \b other is fully included in \b this.
1782  * The main difference is that this method is not expected to throw exception.
1783  * This method has two outputs :
1784  *
1785  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1786  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1787  */
1788 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1789 {
1790   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1791   DataArrayInt *commonCells=0,*commonCellsI=0;
1792   int thisNbCells=getNumberOfCells();
1793   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1795   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1796   int otherNbCells=other->getNumberOfCells();
1797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1798   arr2->alloc(otherNbCells,1);
1799   arr2->fillWithZero();
1800   int *arr2Ptr=arr2->getPointer();
1801   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1802   for(int i=0;i<nbOfCommon;i++)
1803     {
1804       int start=commonCellsPtr[commonCellsIPtr[i]];
1805       if(start<thisNbCells)
1806         {
1807           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1808             {
1809               int sig=commonCellsPtr[j]>0?1:-1;
1810               int val=std::abs(commonCellsPtr[j])-1;
1811               if(val>=thisNbCells)
1812                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1813             }
1814         }
1815     }
1816   arr2->setName(other->getName());
1817   if(arr2->presenceOfValue(0))
1818     return false;
1819   arr=arr2.retn();
1820   return true;
1821 }
1822
1823 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1824 {
1825   if(!other)
1826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1827   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1828   if(!otherC)
1829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1830   std::vector<const MEDCouplingUMesh *> ms(2);
1831   ms[0]=this;
1832   ms[1]=otherC;
1833   return MergeUMeshesOnSameCoords(ms);
1834 }
1835
1836 /*!
1837  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1838  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1839  * cellIds is not given explicitely but by a range python like.
1840  * 
1841  * \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.
1842  * \return a newly allocated
1843  * 
1844  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1845  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1846  */
1847 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1848 {
1849   if(getMeshDimension()!=-1)
1850     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1851   else
1852     {
1853       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1854       if(newNbOfCells!=1)
1855         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1856       if(start!=0)
1857         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1858       incrRef();
1859       return const_cast<MEDCouplingUMesh *>(this);
1860     }
1861 }
1862
1863 /*!
1864  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1865  * The result mesh shares or not the node coordinates array with \a this mesh depending
1866  * on \a keepCoords parameter.
1867  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1868  *           to write this mesh to the MED file, its cells must be sorted using
1869  *           sortCellsInMEDFileFrmt().
1870  *  \param [in] begin - an array of cell ids to include to the new mesh.
1871  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1872  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1873  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1874  *         by calling zipCoords().
1875  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1876  *         to delete this mesh using decrRef() as it is no more needed. 
1877  *  \throw If the coordinates array is not set.
1878  *  \throw If the nodal connectivity of cells is not defined.
1879  *  \throw If any cell id in the array \a begin is not valid.
1880  *
1881  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1882  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1883  */
1884 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1885 {
1886   if(getMeshDimension()!=-1)
1887     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1888   else
1889     {
1890       if(end-begin!=1)
1891         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1892       if(begin[0]!=0)
1893         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1894       incrRef();
1895       return const_cast<MEDCouplingUMesh *>(this);
1896     }
1897 }
1898
1899 /*!
1900  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1901  *
1902  * 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.
1903  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1904  * The number of cells of \b this will remain the same with this method.
1905  *
1906  * \param [in] begin begin of cell ids (included) of cells in this to assign
1907  * \param [in] end end of cell ids (excluded) of cells in this to assign
1908  * \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 ).
1909  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1910  */
1911 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1912 {
1913   checkConnectivityFullyDefined();
1914   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1915   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1917   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1918     {
1919       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1920       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1921       throw INTERP_KERNEL::Exception(oss.str().c_str());
1922     }
1923   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1924   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1925     {
1926       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1927       throw INTERP_KERNEL::Exception(oss.str().c_str());
1928     }
1929   int nbOfCells=getNumberOfCells();
1930   bool easyAssign=true;
1931   const int *connI=_nodal_connec_index->getConstPointer();
1932   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1933   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1934     {
1935       if(*it>=0 && *it<nbOfCells)
1936         {
1937           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1938         }
1939       else
1940         {
1941           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1942           throw INTERP_KERNEL::Exception(oss.str().c_str());
1943         }
1944     }
1945   if(easyAssign)
1946     {
1947       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1948       computeTypes();
1949     }
1950   else
1951     {
1952       DataArrayInt *arrOut=0,*arrIOut=0;
1953       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1954                                                arrOut,arrIOut);
1955       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1956       setConnectivity(arrOut,arrIOut,true);
1957     }
1958 }
1959
1960 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1961 {
1962   checkConnectivityFullyDefined();
1963   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1964   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1966   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1967     {
1968       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1969       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1970       throw INTERP_KERNEL::Exception(oss.str().c_str());
1971     }
1972   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1973   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1974     {
1975       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1976       throw INTERP_KERNEL::Exception(oss.str().c_str());
1977     }
1978   int nbOfCells=getNumberOfCells();
1979   bool easyAssign=true;
1980   const int *connI=_nodal_connec_index->getConstPointer();
1981   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1982   int it=start;
1983   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1984     {
1985       if(it>=0 && it<nbOfCells)
1986         {
1987           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1988         }
1989       else
1990         {
1991           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1992           throw INTERP_KERNEL::Exception(oss.str().c_str());
1993         }
1994     }
1995   if(easyAssign)
1996     {
1997       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1998       computeTypes();
1999     }
2000   else
2001     {
2002       DataArrayInt *arrOut=0,*arrIOut=0;
2003       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2004                                                 arrOut,arrIOut);
2005       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2006       setConnectivity(arrOut,arrIOut,true);
2007     }
2008 }                      
2009
2010 /*!
2011  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2012  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2013  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2014  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2015  *
2016  * \param [in] begin input start of array of node ids.
2017  * \param [in] end input end of array of node ids.
2018  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2019  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2020  */
2021 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2022 {
2023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2024   checkConnectivityFullyDefined();
2025   int tmp=-1;
2026   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2027   std::vector<bool> fastFinder(sz,false);
2028   for(const int *work=begin;work!=end;work++)
2029     if(*work>=0 && *work<sz)
2030       fastFinder[*work]=true;
2031   int nbOfCells=getNumberOfCells();
2032   const int *conn=getNodalConnectivity()->getConstPointer();
2033   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2034   for(int i=0;i<nbOfCells;i++)
2035     {
2036       int ref=0,nbOfHit=0;
2037       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2038         if(*work2>=0)
2039           {
2040             ref++;
2041             if(fastFinder[*work2])
2042               nbOfHit++;
2043           }
2044       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2045         cellIdsKept->pushBackSilent(i);
2046     }
2047   cellIdsKeptArr=cellIdsKept.retn();
2048 }
2049
2050 /*!
2051  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2052  * this->getMeshDimension(), that bound some cells of \a this mesh.
2053  * The cells of lower dimension to include to the result mesh are selected basing on
2054  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2055  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2056  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2057  * created mesh shares the node coordinates array with \a this mesh. 
2058  *  \param [in] begin - the array of node ids.
2059  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2060  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2061  *         array \a begin are added, else cells whose any node is in the
2062  *         array \a begin are added.
2063  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2064  *         to delete this mesh using decrRef() as it is no more needed. 
2065  *  \throw If the coordinates array is not set.
2066  *  \throw If the nodal connectivity of cells is not defined.
2067  *  \throw If any node id in \a begin is not valid.
2068  *
2069  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2070  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2071  */
2072 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2073 {
2074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2075   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2076   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2077   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2078   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2079 }
2080
2081 /*!
2082  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2083  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2084  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2085  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2086  *         by calling zipCoords().
2087  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2088  *         to delete this mesh using decrRef() as it is no more needed. 
2089  *  \throw If the coordinates array is not set.
2090  *  \throw If the nodal connectivity of cells is not defined.
2091  *
2092  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2093  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2094  */
2095 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2096 {
2097   DataArrayInt *desc=DataArrayInt::New();
2098   DataArrayInt *descIndx=DataArrayInt::New();
2099   DataArrayInt *revDesc=DataArrayInt::New();
2100   DataArrayInt *revDescIndx=DataArrayInt::New();
2101   //
2102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2103   revDesc->decrRef();
2104   desc->decrRef();
2105   descIndx->decrRef();
2106   int nbOfCells=meshDM1->getNumberOfCells();
2107   const int *revDescIndxC=revDescIndx->getConstPointer();
2108   std::vector<int> boundaryCells;
2109   for(int i=0;i<nbOfCells;i++)
2110     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2111       boundaryCells.push_back(i);
2112   revDescIndx->decrRef();
2113   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2114   return ret;
2115 }
2116
2117 /*!
2118  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2119  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2120  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2121  */
2122 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2123 {
2124   checkFullyDefined();
2125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2128   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2129   //
2130   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2131   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2132   //
2133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2134   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2135   const int *revDescPtr=revDesc->getConstPointer();
2136   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2137   int nbOfCells=getNumberOfCells();
2138   std::vector<bool> ret1(nbOfCells,false);
2139   int sz=0;
2140   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2141     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2142       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2143   //
2144   DataArrayInt *ret2=DataArrayInt::New();
2145   ret2->alloc(sz,1);
2146   int *ret2Ptr=ret2->getPointer();
2147   sz=0;
2148   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2149     if(*it)
2150       *ret2Ptr++=sz;
2151   ret2->setName("BoundaryCells");
2152   return ret2;
2153 }
2154
2155 /*!
2156  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2157  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2158  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2159  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2160  *
2161  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2162  * This method method returns cells ids set s = s1 + s2 where :
2163  * 
2164  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2165  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2166  *
2167  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2168  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2169  *
2170  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2171  * \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
2172  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2173  */
2174 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2175 {
2176   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2177     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2178   checkConnectivityFullyDefined();
2179   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2180   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2181     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2184   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2186   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2187   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2188   DataArrayInt *idsOtherInConsti=0;
2189   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2190   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2191   if(!b)
2192     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2193   std::set<int> s1;
2194   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2195     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2198   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2199   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2201   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2202   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2203   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2204   neighThisPartAuto=0;
2205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2206   const int li[2]={0,1};
2207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2208   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2210   s_renum1->sort();
2211   //
2212   cellIdsRk0=s0arr.retn();
2213   cellIdsRk1=s_renum1.retn();
2214 }
2215
2216 /*!
2217  * 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
2218  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2219  * 
2220  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2221  */
2222 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2223 {
2224   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2228   //
2229   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2230   revDesc=0; desc=0; descIndx=0;
2231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2233   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2234 }
2235
2236 /*!
2237  * Finds nodes lying on the boundary of \a this mesh.
2238  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2239  *          nodes. The caller is to delete this array using decrRef() as it is no
2240  *          more needed.
2241  *  \throw If the coordinates array is not set.
2242  *  \throw If the nodal connectivity of cells is node defined.
2243  *
2244  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2245  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2246  */
2247 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2248 {
2249   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2250   return skin->computeFetchedNodeIds();
2251 }
2252
2253 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2254 {
2255   incrRef();
2256   return const_cast<MEDCouplingUMesh *>(this);
2257 }
2258
2259 /*!
2260  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2261  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2262  * 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.
2263  * 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.
2264  * 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.
2265  *
2266  * \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
2267  *             parameter is altered during the call.
2268  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2269  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2270  * \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.
2271  *
2272  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2273  */
2274 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2275                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2276 {
2277   checkFullyDefined();
2278   otherDimM1OnSameCoords.checkFullyDefined();
2279   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2281   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2283   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2284   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2287   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2288   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2292   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2293   //
2294   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2296   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2297   DataArrayInt *idsTmp=0;
2298   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2300   if(!b)
2301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2302   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2303   DataArrayInt *tmp0=0,*tmp1=0;
2304   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2309   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2310   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2311   //
2312   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2313   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2314   nodeIdsToDuplicate=s3.retn();
2315 }
2316
2317 /*!
2318  * This method operates a modification of the connectivity and coords in \b this.
2319  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2320  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2321  * 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
2322  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2323  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2324  * 
2325  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2326  * 
2327  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2328  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2329  */
2330 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2331 {
2332   int nbOfNodes=getNumberOfNodes();
2333   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2334   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2335 }
2336
2337 /*!
2338  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2339  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2340  * This method is a generalization of shiftNodeNumbersInConn().
2341  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2342  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2343  *         this->getNumberOfNodes(), in "Old to New" mode. 
2344  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2345  *  \throw If the nodal connectivity of cells is not defined.
2346  *
2347  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2348  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2349  */
2350 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2351 {
2352   checkConnectivityFullyDefined();
2353   int *conn=getNodalConnectivity()->getPointer();
2354   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2355   int nbOfCells=getNumberOfCells();
2356   for(int i=0;i<nbOfCells;i++)
2357     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2358       {
2359         int& node=conn[iconn];
2360         if(node>=0)//avoid polyhedron separator
2361           {
2362             node=newNodeNumbersO2N[node];
2363           }
2364       }
2365   _nodal_connec->declareAsNew();
2366   updateTime();
2367 }
2368
2369 /*!
2370  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2371  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2372  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2373  * 
2374  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2375  */
2376 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2377 {
2378   checkConnectivityFullyDefined();
2379   int *conn=getNodalConnectivity()->getPointer();
2380   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2381   int nbOfCells=getNumberOfCells();
2382   for(int i=0;i<nbOfCells;i++)
2383     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2384       {
2385         int& node=conn[iconn];
2386         if(node>=0)//avoid polyhedron separator
2387           {
2388             node+=delta;
2389           }
2390       }
2391   _nodal_connec->declareAsNew();
2392   updateTime();
2393 }
2394
2395 /*!
2396  * This method operates a modification of the connectivity in \b this.
2397  * 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.
2398  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2399  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2400  * 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
2401  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2402  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2403  * 
2404  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2405  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2406  * 
2407  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2408  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2409  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2410  */
2411 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2412 {
2413   checkConnectivityFullyDefined();
2414   std::map<int,int> m;
2415   int val=offset;
2416   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2417     m[*work]=val;
2418   int *conn=getNodalConnectivity()->getPointer();
2419   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2420   int nbOfCells=getNumberOfCells();
2421   for(int i=0;i<nbOfCells;i++)
2422     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2423       {
2424         int& node=conn[iconn];
2425         if(node>=0)//avoid polyhedron separator
2426           {
2427             std::map<int,int>::iterator it=m.find(node);
2428             if(it!=m.end())
2429               node=(*it).second;
2430           }
2431       }
2432   updateTime();
2433 }
2434
2435 /*!
2436  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2437  *
2438  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2439  * After the call of this method the number of cells remains the same as before.
2440  *
2441  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2442  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2443  * be strictly in [0;this->getNumberOfCells()).
2444  *
2445  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2446  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2447  * should be contained in[0;this->getNumberOfCells()).
2448  * 
2449  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2450  */
2451 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2452 {
2453   checkConnectivityFullyDefined();
2454   int nbCells=getNumberOfCells();
2455   const int *array=old2NewBg;
2456   if(check)
2457     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2458   //
2459   const int *conn=_nodal_connec->getConstPointer();
2460   const int *connI=_nodal_connec_index->getConstPointer();
2461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2463   const int *n2oPtr=n2o->begin();
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2465   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2466   newConn->copyStringInfoFrom(*_nodal_connec);
2467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2468   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2469   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2470   //
2471   int *newC=newConn->getPointer();
2472   int *newCI=newConnI->getPointer();
2473   int loc=0;
2474   newCI[0]=loc;
2475   for(int i=0;i<nbCells;i++)
2476     {
2477       int pos=n2oPtr[i];
2478       int nbOfElts=connI[pos+1]-connI[pos];
2479       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2480       loc+=nbOfElts;
2481       newCI[i+1]=loc;
2482     }
2483   //
2484   setConnectivity(newConn,newConnI);
2485   if(check)
2486     free(const_cast<int *>(array));
2487 }
2488
2489 /*!
2490  * Finds cells whose bounding boxes intersect a given bounding box.
2491  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2492  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2493  *         zMax (if in 3D). 
2494  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2495  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2496  *         extent of the bounding box of cell to produce an addition to this bounding box.
2497  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2498  *         cells. The caller is to delete this array using decrRef() as it is no more
2499  *         needed. 
2500  *  \throw If the coordinates array is not set.
2501  *  \throw If the nodal connectivity of cells is not defined.
2502  *
2503  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2504  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2505  */
2506 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2507 {
2508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2509   if(getMeshDimension()==-1)
2510     {
2511       elems->pushBackSilent(0);
2512       return elems.retn();
2513     }
2514   int dim=getSpaceDimension();
2515   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2516   const int* conn      = getNodalConnectivity()->getConstPointer();
2517   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2518   const double* coords = getCoords()->getConstPointer();
2519   int nbOfCells=getNumberOfCells();
2520   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2521     {
2522       for (int i=0; i<dim; i++)
2523         {
2524           elem_bb[i*2]=std::numeric_limits<double>::max();
2525           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2526         }
2527
2528       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2529         {
2530           int node= conn[inode];
2531           if(node>=0)//avoid polyhedron separator
2532             {
2533               for (int idim=0; idim<dim; idim++)
2534                 {
2535                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2536                     {
2537                       elem_bb[idim*2] = coords[node*dim+idim] ;
2538                     }
2539                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2540                     {
2541                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2542                     }
2543                 }
2544             }
2545         }
2546       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2547         elems->pushBackSilent(ielem);
2548     }
2549   return elems.retn();
2550 }
2551
2552 /*!
2553  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2554  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2555  * added in 'elems' parameter.
2556  */
2557 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2558 {
2559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2560   if(getMeshDimension()==-1)
2561     {
2562       elems->pushBackSilent(0);
2563       return elems.retn();
2564     }
2565   int dim=getSpaceDimension();
2566   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2567   const int* conn      = getNodalConnectivity()->getConstPointer();
2568   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2569   const double* coords = getCoords()->getConstPointer();
2570   int nbOfCells=getNumberOfCells();
2571   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2572     {
2573       for (int i=0; i<dim; i++)
2574         {
2575           elem_bb[i*2]=std::numeric_limits<double>::max();
2576           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2577         }
2578
2579       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2580         {
2581           int node= conn[inode];
2582           if(node>=0)//avoid polyhedron separator
2583             {
2584               for (int idim=0; idim<dim; idim++)
2585                 {
2586                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2587                     {
2588                       elem_bb[idim*2] = coords[node*dim+idim] ;
2589                     }
2590                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2591                     {
2592                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2593                     }
2594                 }
2595             }
2596         }
2597       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2598         elems->pushBackSilent(ielem);
2599     }
2600   return elems.retn();
2601 }
2602
2603 /*!
2604  * Returns a type of a cell by its id.
2605  *  \param [in] cellId - the id of the cell of interest.
2606  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2607  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2608  */
2609 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2610 {
2611   const int *ptI=_nodal_connec_index->getConstPointer();
2612   const int *pt=_nodal_connec->getConstPointer();
2613   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2614     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2615   else
2616     {
2617       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2618       throw INTERP_KERNEL::Exception(oss.str().c_str());
2619     }
2620 }
2621
2622 /*!
2623  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2624  * This method does not throw exception if geometric type \a type is not in \a this.
2625  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2626  * The coordinates array is not considered here.
2627  *
2628  * \param [in] type the geometric type
2629  * \return cell ids in this having geometric type \a type.
2630  */
2631 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2632 {
2633   
2634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2635   ret->alloc(0,1);
2636   checkConnectivityFullyDefined();
2637   int nbCells=getNumberOfCells();
2638   int mdim=getMeshDimension();
2639   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2640   if(mdim!=(int)cm.getDimension())
2641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2642   const int *ptI=_nodal_connec_index->getConstPointer();
2643   const int *pt=_nodal_connec->getConstPointer();
2644   for(int i=0;i<nbCells;i++)
2645     {
2646       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2647         ret->pushBackSilent(i);
2648     }
2649   return ret.retn();
2650 }
2651
2652 /*!
2653  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2654  */
2655 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2656 {
2657   const int *ptI=_nodal_connec_index->getConstPointer();
2658   const int *pt=_nodal_connec->getConstPointer();
2659   int nbOfCells=getNumberOfCells();
2660   int ret=0;
2661   for(int i=0;i<nbOfCells;i++)
2662     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2663       ret++;
2664   return ret;
2665 }
2666
2667 /*!
2668  * Returns the nodal connectivity of a given cell.
2669  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2670  * all returned node ids can be used in getCoordinatesOfNode().
2671  *  \param [in] cellId - an id of the cell of interest.
2672  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2673  *         cleared before the appending.
2674  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2675  */
2676 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2677 {
2678   const int *ptI=_nodal_connec_index->getConstPointer();
2679   const int *pt=_nodal_connec->getConstPointer();
2680   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2681     if(*w>=0)
2682       conn.push_back(*w);
2683 }
2684
2685 std::string MEDCouplingUMesh::simpleRepr() const
2686 {
2687   static const char msg0[]="No coordinates specified !";
2688   std::ostringstream ret;
2689   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2690   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2691   int tmpp1,tmpp2;
2692   double tt=getTime(tmpp1,tmpp2);
2693   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2694   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2695   if(_mesh_dim>=-1)
2696     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2697   else
2698     { ret << " Mesh dimension has not been set or is invalid !"; }
2699   if(_coords!=0)
2700     {
2701       const int spaceDim=getSpaceDimension();
2702       ret << spaceDim << "\nInfo attached on space dimension : ";
2703       for(int i=0;i<spaceDim;i++)
2704         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2705       ret << "\n";
2706     }
2707   else
2708     ret << msg0 << "\n";
2709   ret << "Number of nodes : ";
2710   if(_coords!=0)
2711     ret << getNumberOfNodes() << "\n";
2712   else
2713     ret << msg0 << "\n";
2714   ret << "Number of cells : ";
2715   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2716     ret << getNumberOfCells() << "\n";
2717   else
2718     ret << "No connectivity specified !" << "\n";
2719   ret << "Cell types present : ";
2720   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2721     {
2722       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2723       ret << cm.getRepr() << " ";
2724     }
2725   ret << "\n";
2726   return ret.str();
2727 }
2728
2729 std::string MEDCouplingUMesh::advancedRepr() const
2730 {
2731   std::ostringstream ret;
2732   ret << simpleRepr();
2733   ret << "\nCoordinates array : \n___________________\n\n";
2734   if(_coords)
2735     _coords->reprWithoutNameStream(ret);
2736   else
2737     ret << "No array set !\n";
2738   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2739   reprConnectivityOfThisLL(ret);
2740   return ret.str();
2741 }
2742
2743 /*!
2744  * This method returns a C++ code that is a dump of \a this.
2745  * This method will throw if this is not fully defined.
2746  */
2747 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2748 {
2749   static const char coordsName[]="coords";
2750   static const char connName[]="conn";
2751   static const char connIName[]="connI";
2752   checkFullyDefined();
2753   std::ostringstream ret; ret << "// coordinates" << std::endl;
2754   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2755   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2756   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2757   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2758   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2759   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2760   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2761   return ret.str();
2762 }
2763
2764 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2765 {
2766   std::ostringstream ret;
2767   reprConnectivityOfThisLL(ret);
2768   return ret.str();
2769 }
2770
2771 /*!
2772  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2773  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2774  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2775  * some algos).
2776  * 
2777  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2778  * 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
2779  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2780  */
2781 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2782 {
2783   int mdim=getMeshDimension();
2784   if(mdim<0)
2785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2786   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2788   bool needToCpyCT=true;
2789   if(!_nodal_connec)
2790     {
2791       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2792       needToCpyCT=false;
2793     }
2794   else
2795     {
2796       tmp1=_nodal_connec;
2797       tmp1->incrRef();
2798     }
2799   if(!_nodal_connec_index)
2800     {
2801       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2802       needToCpyCT=false;
2803     }
2804   else
2805     {
2806       tmp2=_nodal_connec_index;
2807       tmp2->incrRef();
2808     }
2809   ret->setConnectivity(tmp1,tmp2,false);
2810   if(needToCpyCT)
2811     ret->_types=_types;
2812   if(!_coords)
2813     {
2814       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2815       ret->setCoords(coords);
2816     }
2817   else
2818     ret->setCoords(_coords);
2819   return ret.retn();
2820 }
2821
2822 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2823 {
2824   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2825     {
2826       int nbOfCells=getNumberOfCells();
2827       const int *c=_nodal_connec->getConstPointer();
2828       const int *ci=_nodal_connec_index->getConstPointer();
2829       for(int i=0;i<nbOfCells;i++)
2830         {
2831           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2832           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2833           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2834           stream << "\n";
2835         }
2836     }
2837   else
2838     stream << "Connectivity not defined !\n";
2839 }
2840
2841 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2842 {
2843   const int *ptI=_nodal_connec_index->getConstPointer();
2844   const int *pt=_nodal_connec->getConstPointer();
2845   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2846     return ptI[cellId+1]-ptI[cellId]-1;
2847   else
2848     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2849 }
2850
2851 /*!
2852  * Returns types of cells of the specified part of \a this mesh.
2853  * This method avoids computing sub-mesh explicitely to get its types.
2854  *  \param [in] begin - an array of cell ids of interest.
2855  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2856  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2857  *         describing the cell types. 
2858  *  \throw If the coordinates array is not set.
2859  *  \throw If the nodal connectivity of cells is not defined.
2860  *  \sa getAllTypes()
2861  */
2862 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2863 {
2864   checkFullyDefined();
2865   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2866   const int *conn=_nodal_connec->getConstPointer();
2867   const int *connIndex=_nodal_connec_index->getConstPointer();
2868   for(const int *w=begin;w!=end;w++)
2869     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2870   return ret;
2871 }
2872
2873 /*!
2874  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2875  * a set of types of cells constituting \a this mesh. 
2876  * This method is for advanced users having prepared their connectivity before. For
2877  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2878  *  \param [in] conn - the nodal connectivity array. 
2879  *  \param [in] connIndex - the nodal connectivity index array.
2880  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2881  *         mesh is updated.
2882  */
2883 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2884 {
2885   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2886   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2887   if(isComputingTypes)
2888     computeTypes();
2889   declareAsNew();
2890 }
2891
2892 /*!
2893  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2894  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2895  */
2896 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2897                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2898                                                                                 _types(other._types)
2899 {
2900   if(other._nodal_connec)
2901     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2902   if(other._nodal_connec_index)
2903     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2904 }
2905
2906 MEDCouplingUMesh::~MEDCouplingUMesh()
2907 {
2908   if(_nodal_connec)
2909     _nodal_connec->decrRef();
2910   if(_nodal_connec_index)
2911     _nodal_connec_index->decrRef();
2912 }
2913
2914 /*!
2915  * Recomputes a set of cell types of \a this mesh. For more info see
2916  * \ref MEDCouplingUMeshNodalConnectivity.
2917  */
2918 void MEDCouplingUMesh::computeTypes()
2919 {
2920   if(_nodal_connec && _nodal_connec_index)
2921     {
2922       _types.clear();
2923       const int *conn=_nodal_connec->getConstPointer();
2924       const int *connIndex=_nodal_connec_index->getConstPointer();
2925       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2926       if (nbOfElem > 0)
2927         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2928           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2929     }
2930 }
2931
2932 /*!
2933  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2934  */
2935 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2936 {
2937   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2938     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2939 }
2940
2941 /*!
2942  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2943  */
2944 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2945 {
2946   if(!_nodal_connec_index || !_nodal_connec)
2947     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2948 }
2949
2950 /*!
2951  * Returns a number of cells constituting \a this mesh. 
2952  *  \return int - the number of cells in \a this mesh.
2953  *  \throw If the nodal connectivity of cells is not defined.
2954  */
2955 int MEDCouplingUMesh::getNumberOfCells() const
2956
2957   if(_nodal_connec_index)
2958     return _nodal_connec_index->getNumberOfTuples()-1;
2959   else
2960     if(_mesh_dim==-1)
2961       return 1;
2962     else
2963       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2964 }
2965
2966 /*!
2967  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
2968  * mesh. For more info see \ref MEDCouplingMeshesPage.
2969  *  \return int - the dimension of \a this mesh.
2970  *  \throw If the mesh dimension is not defined using setMeshDimension().
2971  */
2972 int MEDCouplingUMesh::getMeshDimension() const
2973 {
2974   if(_mesh_dim<-1)
2975     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2976   return _mesh_dim;
2977 }
2978
2979 /*!
2980  * Returns a length of the nodal connectivity array.
2981  * This method is for test reason. Normally the integer returned is not useable by
2982  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
2983  *  \return int - the length of the nodal connectivity array.
2984  */
2985 int MEDCouplingUMesh::getMeshLength() const
2986 {
2987   return _nodal_connec->getNbOfElems();
2988 }
2989
2990 /*!
2991  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2992  */
2993 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2994 {
2995   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2996   tinyInfo.push_back(getMeshDimension());
2997   tinyInfo.push_back(getNumberOfCells());
2998   if(_nodal_connec)
2999     tinyInfo.push_back(getMeshLength());
3000   else
3001     tinyInfo.push_back(-1);
3002 }
3003
3004 /*!
3005  * First step of unserialization process.
3006  */
3007 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3008 {
3009   return tinyInfo[6]<=0;
3010 }
3011
3012 /*!
3013  * Second step of serialization process.
3014  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3015  */
3016 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3017 {
3018   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3019   if(tinyInfo[5]!=-1)
3020     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3021 }
3022
3023 /*!
3024  * Third and final step of serialization process.
3025  */
3026 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3027 {
3028   MEDCouplingPointSet::serialize(a1,a2);
3029   if(getMeshDimension()>-1)
3030     {
3031       a1=DataArrayInt::New();
3032       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3033       int *ptA1=a1->getPointer();
3034       const int *conn=getNodalConnectivity()->getConstPointer();
3035       const int *index=getNodalConnectivityIndex()->getConstPointer();
3036       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3037       std::copy(conn,conn+getMeshLength(),ptA1);
3038     }
3039   else
3040     a1=0;
3041 }
3042
3043 /*!
3044  * Second and final unserialization process.
3045  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3046  */
3047 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3048 {
3049   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3050   setMeshDimension(tinyInfo[5]);
3051   if(tinyInfo[7]!=-1)
3052     {
3053       // Connectivity
3054       const int *recvBuffer=a1->getConstPointer();
3055       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3056       myConnecIndex->alloc(tinyInfo[6]+1,1);
3057       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3058       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3059       myConnec->alloc(tinyInfo[7],1);
3060       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3061       setConnectivity(myConnec, myConnecIndex);
3062     }
3063 }
3064
3065 /*!
3066  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3067  * CellIds are given using range specified by a start an end and step.
3068  */
3069 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3070 {
3071   checkFullyDefined();
3072   int ncell=getNumberOfCells();
3073   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3074   ret->_mesh_dim=_mesh_dim;
3075   ret->setCoords(_coords);
3076   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3077   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3078   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3079   int work=start;
3080   const int *conn=_nodal_connec->getConstPointer();
3081   const int *connIndex=_nodal_connec_index->getConstPointer();
3082   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3083     {
3084       if(work>=0 && work<ncell)
3085         {
3086           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3087         }
3088       else
3089         {
3090           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3091           throw INTERP_KERNEL::Exception(oss.str().c_str());
3092         }
3093     }
3094   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3095   int *newConnPtr=newConn->getPointer();
3096   std::set<INTERP_KERNEL::NormalizedCellType> types;
3097   work=start;
3098   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3099     {
3100       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3101       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3102     }
3103   ret->setConnectivity(newConn,newConnI,false);
3104   ret->_types=types;
3105   ret->copyTinyInfoFrom(this);
3106   return ret.retn();
3107 }
3108
3109 /*!
3110  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3111  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3112  * The return newly allocated mesh will share the same coordinates as \a this.
3113  */
3114 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3115 {
3116   checkFullyDefined();
3117   int ncell=getNumberOfCells();
3118   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3119   ret->_mesh_dim=_mesh_dim;
3120   ret->setCoords(_coords);
3121   std::size_t nbOfElemsRet=std::distance(begin,end);
3122   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3123   connIndexRet[0]=0;
3124   const int *conn=_nodal_connec->getConstPointer();
3125   const int *connIndex=_nodal_connec_index->getConstPointer();
3126   int newNbring=0;
3127   for(const int *work=begin;work!=end;work++,newNbring++)
3128     {
3129       if(*work>=0 && *work<ncell)
3130         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3131       else
3132         {
3133           free(connIndexRet);
3134           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3135           throw INTERP_KERNEL::Exception(oss.str().c_str());
3136         }
3137     }
3138   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3139   int *connRetWork=connRet;
3140   std::set<INTERP_KERNEL::NormalizedCellType> types;
3141   for(const int *work=begin;work!=end;work++)
3142     {
3143       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3144       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3145     }
3146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3147   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3148   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3149   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3150   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3151   ret->_types=types;
3152   ret->copyTinyInfoFrom(this);
3153   return ret.retn();
3154 }
3155
3156 /*!
3157  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3158  * mesh.<br>
3159  * For 1D cells, the returned field contains lengths.<br>
3160  * For 2D cells, the returned field contains areas.<br>
3161  * For 3D cells, the returned field contains volumes.
3162  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3163  *         orientation, i.e. the volume is always positive.
3164  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3165  *         and one time . The caller is to delete this field using decrRef() as it is no
3166  *         more needed.
3167  */
3168 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3169 {
3170   std::string name="MeasureOfMesh_";
3171   name+=getName();
3172   int nbelem=getNumberOfCells();
3173   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3174   field->setName(name.c_str());
3175   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3176   array->alloc(nbelem,1);
3177   double *area_vol=array->getPointer();
3178   field->setArray(array) ; array=0;
3179   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3180   field->synchronizeTimeWithMesh();
3181   if(getMeshDimension()!=-1)
3182     {
3183       int ipt;
3184       INTERP_KERNEL::NormalizedCellType type;
3185       int dim_space=getSpaceDimension();
3186       const double *coords=getCoords()->getConstPointer();
3187       const int *connec=getNodalConnectivity()->getConstPointer();
3188       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3189       for(int iel=0;iel<nbelem;iel++)
3190         {
3191           ipt=connec_index[iel];
3192           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3193           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);
3194         }
3195       if(isAbs)
3196         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3197     }
3198   else
3199     {
3200       area_vol[0]=std::numeric_limits<double>::max();
3201     }
3202   return field.retn();
3203 }
3204
3205 /*!
3206  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3207  * mesh.<br>
3208  * For 1D cells, the returned array contains lengths.<br>
3209  * For 2D cells, the returned array contains areas.<br>
3210  * For 3D cells, the returned array contains volumes.
3211  * This method avoids building explicitly a part of \a this mesh to perform the work.
3212  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3213  *         orientation, i.e. the volume is always positive.
3214  *  \param [in] begin - an array of cell ids of interest.
3215  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3216  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3217  *          delete this array using decrRef() as it is no more needed.
3218  * 
3219  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3220  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3221  *  \sa getMeasureField()
3222  */
3223 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3224 {
3225   std::string name="PartMeasureOfMesh_";
3226   name+=getName();
3227   int nbelem=(int)std::distance(begin,end);
3228   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3229   array->setName(name.c_str());
3230   array->alloc(nbelem,1);
3231   double *area_vol=array->getPointer();
3232   if(getMeshDimension()!=-1)
3233     {
3234       int ipt;
3235       INTERP_KERNEL::NormalizedCellType type;
3236       int dim_space=getSpaceDimension();
3237       const double *coords=getCoords()->getConstPointer();
3238       const int *connec=getNodalConnectivity()->getConstPointer();
3239       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3240       for(const int *iel=begin;iel!=end;iel++)
3241         {
3242           ipt=connec_index[*iel];
3243           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3244           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3245         }
3246       if(isAbs)
3247         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3248     }
3249   else
3250     {
3251       area_vol[0]=std::numeric_limits<double>::max();
3252     }
3253   return array.retn();
3254 }
3255
3256 /*!
3257  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3258  * \a this one. The returned field contains the dual cell volume for each corresponding
3259  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3260  *  the dual mesh in P1 sens of \a this.<br>
3261  * For 1D cells, the returned field contains lengths.<br>
3262  * For 2D cells, the returned field contains areas.<br>
3263  * For 3D cells, the returned field contains volumes.
3264  * This method is useful to check "P1*" conservative interpolators.
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  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3268  *          nodes and one time. The caller is to delete this array using decrRef() as
3269  *          it is no more needed.
3270  */
3271 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3272 {
3273   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3274   std::string name="MeasureOnNodeOfMesh_";
3275   name+=getName();
3276   int nbNodes=getNumberOfNodes();
3277   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3278   double cst=1./((double)getMeshDimension()+1.);
3279   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3280   array->alloc(nbNodes,1);
3281   double *valsToFill=array->getPointer();
3282   std::fill(valsToFill,valsToFill+nbNodes,0.);
3283   const double *values=tmp->getArray()->getConstPointer();
3284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3286   getReverseNodalConnectivity(da,daInd);
3287   const int *daPtr=da->getConstPointer();
3288   const int *daIPtr=daInd->getConstPointer();
3289   for(int i=0;i<nbNodes;i++)
3290     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3291       valsToFill[i]+=cst*values[*cell];
3292   ret->setMesh(this);
3293   ret->setArray(array);
3294   return ret.retn();
3295 }
3296
3297 /*!
3298  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3299  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3300  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3301  * and are normalized.
3302  * <br> \a this can be either 
3303  * - a  2D mesh in 2D or 3D space or 
3304  * - an 1D mesh in 2D space.
3305  * 
3306  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3307  *          cells and one time. The caller is to delete this field using decrRef() as
3308  *          it is no more needed.
3309  *  \throw If the nodal connectivity of cells is not defined.
3310  *  \throw If the coordinates array is not set.
3311  *  \throw If the mesh dimension is not set.
3312  *  \throw If the mesh and space dimension is not as specified above.
3313  */
3314 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3315 {
3316   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3317     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3318   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3319   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3320   int nbOfCells=getNumberOfCells();
3321   int nbComp=getMeshDimension()+1;
3322   array->alloc(nbOfCells,nbComp);
3323   double *vals=array->getPointer();
3324   const int *connI=_nodal_connec_index->getConstPointer();
3325   const int *conn=_nodal_connec->getConstPointer();
3326   const double *coords=_coords->getConstPointer();
3327   if(getMeshDimension()==2)
3328     {
3329       if(getSpaceDimension()==3)
3330         {
3331           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3332           const double *locPtr=loc->getConstPointer();
3333           for(int i=0;i<nbOfCells;i++,vals+=3)
3334             {
3335               int offset=connI[i];
3336               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3337               double n=INTERP_KERNEL::norm<3>(vals);
3338               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3339             }
3340         }
3341       else
3342         {
3343           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3344           const double *isAbsPtr=isAbs->getArray()->begin();
3345           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3346             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3347         }
3348     }
3349   else//meshdimension==1
3350     {
3351       double tmp[2];
3352       for(int i=0;i<nbOfCells;i++)
3353         {
3354           int offset=connI[i];
3355           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3356           double n=INTERP_KERNEL::norm<2>(tmp);
3357           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3358           *vals++=-tmp[1];
3359           *vals++=tmp[0];
3360         }
3361     }
3362   ret->setArray(array);
3363   ret->setMesh(this);
3364   ret->synchronizeTimeWithSupport();
3365   return ret.retn();
3366 }
3367
3368 /*!
3369  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3370  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3371  * and are normalized.
3372  * <br> \a this can be either 
3373  * - a  2D mesh in 2D or 3D space or 
3374  * - an 1D mesh in 2D space.
3375  * 
3376  * This method avoids building explicitly a part of \a this mesh to perform the work.
3377  *  \param [in] begin - an array of cell ids of interest.
3378  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3379  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3380  *          cells and one time. The caller is to delete this field using decrRef() as
3381  *          it is no more needed.
3382  *  \throw If the nodal connectivity of cells is not defined.
3383  *  \throw If the coordinates array is not set.
3384  *  \throw If the mesh dimension is not set.
3385  *  \throw If the mesh and space dimension is not as specified above.
3386  *  \sa buildOrthogonalField()
3387  *
3388  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3389  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3390  */
3391 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3392 {
3393   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3394     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3395   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3396   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3397   std::size_t nbelems=std::distance(begin,end);
3398   int nbComp=getMeshDimension()+1;
3399   array->alloc((int)nbelems,nbComp);
3400   double *vals=array->getPointer();
3401   const int *connI=_nodal_connec_index->getConstPointer();
3402   const int *conn=_nodal_connec->getConstPointer();
3403   const double *coords=_coords->getConstPointer();
3404   if(getMeshDimension()==2)
3405     {
3406       if(getSpaceDimension()==3)
3407         {
3408           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3409           const double *locPtr=loc->getConstPointer();
3410           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3411             {
3412               int offset=connI[*i];
3413               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3414               double n=INTERP_KERNEL::norm<3>(vals);
3415               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3416             }
3417         }
3418       else
3419         {
3420           for(std::size_t i=0;i<nbelems;i++)
3421             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3422         }
3423     }
3424   else//meshdimension==1
3425     {
3426       double tmp[2];
3427       for(const int *i=begin;i!=end;i++)
3428         {
3429           int offset=connI[*i];
3430           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3431           double n=INTERP_KERNEL::norm<2>(tmp);
3432           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3433           *vals++=-tmp[1];
3434           *vals++=tmp[0];
3435         }
3436     }
3437   ret->setArray(array);
3438   ret->setMesh(this);
3439   ret->synchronizeTimeWithSupport();
3440   return ret.retn();
3441 }
3442
3443 /*!
3444  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3445  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3446  * and are \b not normalized.
3447  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3448  *          cells and one time. The caller is to delete this field using decrRef() as
3449  *          it is no more needed.
3450  *  \throw If the nodal connectivity of cells is not defined.
3451  *  \throw If the coordinates array is not set.
3452  *  \throw If \a this->getMeshDimension() != 1.
3453  *  \throw If \a this mesh includes cells of type other than SEG2.
3454  */
3455 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3456 {
3457    if(getMeshDimension()!=1)
3458     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3459    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3460      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3461    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3462    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3463    int nbOfCells=getNumberOfCells();
3464    int spaceDim=getSpaceDimension();
3465    array->alloc(nbOfCells,spaceDim);
3466    double *pt=array->getPointer();
3467    const double *coo=getCoords()->getConstPointer();
3468    std::vector<int> conn;
3469    conn.reserve(2);
3470    for(int i=0;i<nbOfCells;i++)
3471      {
3472        conn.resize(0);
3473        getNodeIdsOfCell(i,conn);
3474        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3475      }
3476    ret->setArray(array);
3477    ret->setMesh(this);
3478    ret->synchronizeTimeWithSupport();
3479    return ret.retn();   
3480 }
3481
3482 /*!
3483  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3484  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3485  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3486  * from. If a result face is shared by two 3D cells, then the face in included twice in
3487  * the result mesh.
3488  *  \param [in] origin - 3 components of a point defining location of the plane.
3489  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3490  *         must be greater than 1e-6.
3491  *  \param [in] eps - half-thickness of the plane.
3492  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3493  *         producing correspondent 2D cells. The caller is to delete this array
3494  *         using decrRef() as it is no more needed.
3495  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3496  *         not share the node coordinates array with \a this mesh. The caller is to
3497  *         delete this mesh using decrRef() as it is no more needed.  
3498  *  \throw If the coordinates array is not set.
3499  *  \throw If the nodal connectivity of cells is not defined.
3500  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3501  *  \throw If magnitude of \a vec is less than 1e-6.
3502  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3503  *  \throw If \a this includes quadratic cells.
3504  */
3505 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3506 {
3507   checkFullyDefined();
3508   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3509     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3511   if(candidates->empty())
3512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3513   std::vector<int> nodes;
3514   DataArrayInt *cellIds1D=0;
3515   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3516   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3519   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3520   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3521   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3522   revDesc2=0; revDescIndx2=0;
3523   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3524   revDesc1=0; revDescIndx1=0;
3525   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3526   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3527   //
3528   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3529   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3530     cut3DCurve[*it]=-1;
3531   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3532   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3533   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3534                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3535                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3536   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3537   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3538   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3539   if(cellIds2->empty())
3540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3541   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3542   ret->setCoords(mDesc1->getCoords());
3543   ret->setConnectivity(conn,connI,true);
3544   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3545   return ret.retn();
3546 }
3547
3548 /*!
3549  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3550 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
3551 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3552 the result mesh.
3553  *  \param [in] origin - 3 components of a point defining location of the plane.
3554  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3555  *         must be greater than 1e-6.
3556  *  \param [in] eps - half-thickness of the plane.
3557  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3558  *         producing correspondent segments. The caller is to delete this array
3559  *         using decrRef() as it is no more needed.
3560  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3561  *         mesh in 3D space. This mesh does not share the node coordinates array with
3562  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3563  *         no more needed. 
3564  *  \throw If the coordinates array is not set.
3565  *  \throw If the nodal connectivity of cells is not defined.
3566  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3567  *  \throw If magnitude of \a vec is less than 1e-6.
3568  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3569  *  \throw If \a this includes quadratic cells.
3570  */
3571 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3572 {
3573   checkFullyDefined();
3574   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3575     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3577   if(candidates->empty())
3578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3579   std::vector<int> nodes;
3580   DataArrayInt *cellIds1D=0;
3581   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3582   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3583   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3584   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3585   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3587   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3588   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3590   //
3591   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3592   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3593     cut3DCurve[*it]=-1;
3594   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3595   int ncellsSub=subMesh->getNumberOfCells();
3596   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3597   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3598                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3599                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3601   conn->alloc(0,1);
3602   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3603   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3604   for(int i=0;i<ncellsSub;i++)
3605     {
3606       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3607         {
3608           if(cut3DSurf[i].first!=-2)
3609             {
3610               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3611               connI->pushBackSilent(conn->getNumberOfTuples());
3612               cellIds2->pushBackSilent(i);
3613             }
3614           else
3615             {
3616               int cellId3DSurf=cut3DSurf[i].second;
3617               int offset=nodalI[cellId3DSurf]+1;
3618               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3619               for(int j=0;j<nbOfEdges;j++)
3620                 {
3621                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3622                   connI->pushBackSilent(conn->getNumberOfTuples());
3623                   cellIds2->pushBackSilent(cellId3DSurf);
3624                 }
3625             }
3626         }
3627     }
3628   if(cellIds2->empty())
3629     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3630   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3631   ret->setCoords(mDesc1->getCoords());
3632   ret->setConnectivity(conn,connI,true);
3633   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3634   return ret.retn();
3635 }
3636
3637 /*!
3638  * Finds cells whose bounding boxes intersect a given plane.
3639  *  \param [in] origin - 3 components of a point defining location of the plane.
3640  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3641  *         must be greater than 1e-6.
3642  *  \param [in] eps - half-thickness of the plane.
3643  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3644  *         cells. The caller is to delete this array using decrRef() as it is no more
3645  *         needed.
3646  *  \throw If the coordinates array is not set.
3647  *  \throw If the nodal connectivity of cells is not defined.
3648  *  \throw If \a this->getSpaceDimension() != 3.
3649  *  \throw If magnitude of \a vec is less than 1e-6.
3650  *  \sa buildSlice3D()
3651  */
3652 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3653 {
3654   checkFullyDefined();
3655   if(getSpaceDimension()!=3)
3656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3657   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3658   if(normm<1e-6)
3659     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3660   double vec2[3];
3661   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3662   double angle=acos(vec[2]/normm);
3663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3664   double bbox[6];
3665   if(angle>eps)
3666     {
3667       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3668       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3669       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3670       mw->setCoords(coo);
3671       mw->getBoundingBox(bbox);
3672       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3673       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3674     }
3675   else
3676     {
3677       getBoundingBox(bbox);
3678       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3679       cellIds=getCellsInBoundingBox(bbox,eps);
3680     }
3681   return cellIds.retn();
3682 }
3683
3684 /*!
3685  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3686  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3687  * No consideration of coordinate is done by this method.
3688  * 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)
3689  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3690  */
3691 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3692 {
3693   if(getMeshDimension()!=1)
3694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3695   int nbCells=getNumberOfCells();
3696   if(nbCells<1)
3697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3698   const int *connI=_nodal_connec_index->getConstPointer();
3699   const int *conn=_nodal_connec->getConstPointer();
3700   int ref=conn[connI[0]+2];
3701   for(int i=1;i<nbCells;i++)
3702     {
3703       if(conn[connI[i]+1]!=ref)
3704         return false;
3705       ref=conn[connI[i]+2];
3706     }
3707   return true;
3708 }
3709
3710 /*!
3711  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3712  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3713  * \param pt reference point of the line
3714  * \param v normalized director vector of the line
3715  * \param eps max precision before throwing an exception
3716  * \param res output of size this->getNumberOfCells
3717  */
3718 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3719 {
3720   if(getMeshDimension()!=1)
3721     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3722    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3723      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3724    if(getSpaceDimension()!=3)
3725      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3726    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3727    const double *fPtr=f->getArray()->getConstPointer();
3728    double tmp[3];
3729    for(int i=0;i<getNumberOfCells();i++)
3730      {
3731        const double *tmp1=fPtr+3*i;
3732        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3733        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3734        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3735        double n1=INTERP_KERNEL::norm<3>(tmp);
3736        n1/=INTERP_KERNEL::norm<3>(tmp1);
3737        if(n1>eps)
3738          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3739      }
3740    const double *coo=getCoords()->getConstPointer();
3741    for(int i=0;i<getNumberOfNodes();i++)
3742      {
3743        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3744        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3745        res[i]=std::accumulate(tmp,tmp+3,0.);
3746      }
3747 }
3748
3749 /*!
3750  * 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. 
3751  * \a this is expected to be a mesh so that its space dimension is equal to its
3752  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3753  * 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).
3754  
3755  * 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
3756  * 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).
3757  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3758  *
3759  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3760  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3761  *
3762  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3763  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3764  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3765  * \return the positive value of the distance.
3766  * \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
3767  * dimension - 1.
3768  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3769  */
3770 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3771 {
3772   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3773   if(meshDim!=spaceDim-1)
3774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3775   if(meshDim!=2 && meshDim!=1)
3776     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3777   checkFullyDefined();
3778   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3779     { 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()); }
3780   DataArrayInt *ret1=0;
3781   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3782   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3784   cellId=*ret1Safe->begin();
3785   return *ret0->begin();
3786 }
3787
3788 /*!
3789  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3790  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3791  * 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
3792  * 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).
3793  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3794  * 
3795  * \a this is expected to be a mesh so that its space dimension is equal to its
3796  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3797  * 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).
3798  *
3799  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3800  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3801  *
3802  * \param [in] pts the list of points in which each tuple represents a point
3803  * \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.
3804  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3805  * \throw if number of components of \a pts is not equal to the space dimension.
3806  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3807  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3808  */
3809 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3810 {
3811   if(!pts)
3812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3813   pts->checkAllocated();
3814   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3815   if(meshDim!=spaceDim-1)
3816     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3817   if(meshDim!=2 && meshDim!=1)
3818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3819   if(pts->getNumberOfComponents()!=spaceDim)
3820     {
3821       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3822       throw INTERP_KERNEL::Exception(oss.str().c_str());
3823     }
3824   checkFullyDefined();
3825   int nbCells=getNumberOfCells();
3826   if(nbCells==0)
3827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3828   int nbOfPts=pts->getNumberOfTuples();
3829   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3831   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3832   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3833   std::vector<double> bbox;
3834   getBoundingBoxForBBTree(bbox);
3835   switch(spaceDim)
3836     {
3837     case 3:
3838       {
3839         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3840         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3841           {
3842             double x=std::numeric_limits<double>::max();
3843             std::vector<int> elems;
3844             myTree.getMinDistanceOfMax(ptsPtr,x);
3845             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3846             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3847           }
3848         break;
3849       }
3850     case 2:
3851       {
3852         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3853         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3854           {
3855             double x=std::numeric_limits<double>::max();
3856             std::vector<int> elems;
3857             myTree.getMinDistanceOfMax(ptsPtr,x);
3858             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3859             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3860           }
3861         break;
3862       }
3863     default:
3864       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3865     }
3866   cellIds=ret1.retn();
3867   return ret0.retn();
3868 }
3869
3870 /*!
3871  * \param [in] pt the start pointer (included) of the coordinates of the point
3872  * \param [in] cellIdsBg the start pointer (included) of cellIds
3873  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3874  * \param [in] nc nodal connectivity
3875  * \param [in] ncI nodal connectivity index
3876  * \param [in,out] ret0 the min distance between \a this and the external input point
3877  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3878  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3879  */
3880 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)
3881 {
3882   cellId=-1;
3883   ret0=std::numeric_limits<double>::max();
3884   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3885     {
3886       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3887         {
3888         case INTERP_KERNEL::NORM_TRI3:
3889           {
3890             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3891             if(tmp<ret0)
3892               { ret0=tmp; cellId=*zeCell; }
3893             break;
3894           }
3895         case INTERP_KERNEL::NORM_QUAD4:
3896         case INTERP_KERNEL::NORM_POLYGON:
3897           {
3898             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3899             if(tmp<ret0)
3900               { ret0=tmp; cellId=*zeCell; }
3901             break;
3902           }
3903         default:
3904           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3905         }
3906     }
3907 }
3908
3909 /*!
3910  * \param [in] pt the start pointer (included) of the coordinates of the point
3911  * \param [in] cellIdsBg the start pointer (included) of cellIds
3912  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3913  * \param [in] nc nodal connectivity
3914  * \param [in] ncI nodal connectivity index
3915  * \param [in,out] ret0 the min distance between \a this and the external input point
3916  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3917  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3918  */
3919 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)
3920 {
3921   cellId=-1;
3922   ret0=std::numeric_limits<double>::max();
3923   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3924     {
3925        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3926         {
3927         case INTERP_KERNEL::NORM_SEG2:
3928           {
3929             std::size_t uselessEntry=0;
3930             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3931             tmp=sqrt(tmp);
3932             if(tmp<ret0)
3933               { ret0=tmp; cellId=*zeCell; }
3934             break;
3935           }
3936         default:
3937           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3938         }
3939     }
3940 }
3941
3942 /*!
3943  * Finds cells in contact with a ball (i.e. a point with precision). 
3944  * \warning This method is suitable if the caller intends to evaluate only one
3945  *          point, for more points getCellsContainingPoints() is recommended as it is
3946  *          faster. 
3947  *  \param [in] pos - array of coordinates of the ball central point.
3948  *  \param [in] eps - ball radius.
3949  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
3950  *         if there are no such cells.
3951  *  \throw If the coordinates array is not set.
3952  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3953  */
3954 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3955 {
3956   std::vector<int> elts;
3957   getCellsContainingPoint(pos,eps,elts);
3958   if(elts.empty())
3959     return -1;
3960   return elts.front();
3961 }
3962
3963 /*!
3964  * Finds cells in contact with a ball (i.e. a point with precision).
3965  * \warning This method is suitable if the caller intends to evaluate only one
3966  *          point, for more points getCellsContainingPoints() is recommended as it is
3967  *          faster. 
3968  *  \param [in] pos - array of coordinates of the ball central point.
3969  *  \param [in] eps - ball radius.
3970  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
3971  *         before inserting ids.
3972  *  \throw If the coordinates array is not set.
3973  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3974  *
3975  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
3976  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
3977  */
3978 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3979 {
3980   std::vector<int> eltsIndex;
3981   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3982 }
3983
3984 /// @cond INTERNAL
3985
3986 namespace ParaMEDMEM
3987 {
3988   template<const int SPACEDIMM>
3989   class DummyClsMCUG
3990   {
3991   public:
3992     static const int MY_SPACEDIM=SPACEDIMM;
3993     static const int MY_MESHDIM=8;
3994     typedef int MyConnType;
3995     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3996     // begin
3997     // useless, but for windows compilation ...
3998     const double* getCoordinatesPtr() const { return 0; }
3999     const int* getConnectivityPtr() const { return 0; }
4000     const int* getConnectivityIndexPtr() const { return 0; }
4001     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4002     // end
4003   };
4004
4005   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4006   {
4007     INTERP_KERNEL::Edge *ret=0;
4008     switch(typ)
4009       {
4010       case INTERP_KERNEL::NORM_SEG2:
4011         {
4012           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4013           break;
4014         }
4015       case INTERP_KERNEL::NORM_SEG3:
4016         {
4017           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4018           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4019           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4020           bool colinearity=inters.areColinears();
4021           delete e1; delete e2;
4022           if(colinearity)
4023             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4024           else
4025             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4026           mapp2[bg[2]].second=false;
4027           break;
4028         }
4029       default:
4030         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4031       }
4032     return ret;
4033   }
4034
4035   /*!
4036    * 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'.
4037    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4038    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4039    */
4040   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4041   {
4042     mapp.clear();
4043     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.
4044     const double *coo=mDesc->getCoords()->getConstPointer();
4045     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4046     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4047     std::set<int> s;
4048     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4049       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4050     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4051       {
4052         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4053         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4054       }
4055     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4056     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4057       {
4058         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4059         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4060       }
4061     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4062       {
4063         if((*it2).second.second)
4064           mapp[(*it2).second.first]=(*it2).first;
4065         ((*it2).second.first)->decrRef();
4066       }
4067     return ret;
4068   }
4069
4070   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4071   {
4072     if(nodeId>=offset2)
4073       {
4074         int locId=nodeId-offset2;
4075         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4076       }
4077     if(nodeId>=offset1)
4078       {
4079         int locId=nodeId-offset1;
4080         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4081       }
4082     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4083   }
4084
4085   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4086                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4087                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4088   {
4089     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4090       {
4091         int eltId1=abs(*desc1)-1;
4092         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4093           {
4094             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4095             if(it==mappRev.end())
4096               {
4097                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4098                 mapp[node]=*it1;
4099                 mappRev[*it1]=node;
4100               }
4101           }
4102       }
4103   }
4104 }
4105
4106 /// @endcond
4107
4108 template<int SPACEDIM>
4109 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4110                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4111 {
4112   std::vector<double> bbox;
4113   eltsIndex.resize(nbOfPoints+1);
4114   eltsIndex[0]=0;
4115   elts.clear();
4116   getBoundingBoxForBBTree(bbox);
4117   int nbOfCells=getNumberOfCells();
4118   const int *conn=_nodal_connec->getConstPointer();
4119   const int *connI=_nodal_connec_index->getConstPointer();
4120   double bb[2*SPACEDIM];
4121   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4122   for(int i=0;i<nbOfPoints;i++)
4123     {
4124       eltsIndex[i+1]=eltsIndex[i];
4125       for(int j=0;j<SPACEDIM;j++)
4126         {
4127           bb[2*j]=pos[SPACEDIM*i+j];
4128           bb[2*j+1]=pos[SPACEDIM*i+j];
4129         }
4130       std::vector<int> candidates;
4131       myTree.getIntersectingElems(bb,candidates);
4132       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4133         {
4134           int sz=connI[(*iter)+1]-connI[*iter]-1;
4135           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4136                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4137                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4138             {
4139               eltsIndex[i+1]++;
4140               elts.push_back(*iter);
4141             }
4142         }
4143     }
4144 }
4145 /*!
4146  * Finds cells in contact with several balls (i.e. points with precision).
4147  * This method is an extension of getCellContainingPoint() and
4148  * getCellsContainingPoint() for the case of multiple points.
4149  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4150  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4151  *         this->getSpaceDimension() * \a nbOfPoints 
4152  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4153  *  \param [in] eps - radius of balls (i.e. the precision).
4154  *  \param [in,out] elts - vector returning ids of found cells.
4155  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4156  *         dividing cell ids in \a elts into groups each referring to one
4157  *         point. Its every element (except the last one) is an index pointing to the
4158  *         first id of a group of cells. For example cells in contact with the *i*-th
4159  *         point are described by following range of indices:
4160  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4161  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4162  *         Number of cells in contact with the *i*-th point is
4163  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4164  *  \throw If the coordinates array is not set.
4165  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4166  *
4167  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4168  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4169  */
4170 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4171                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4172 {
4173   int spaceDim=getSpaceDimension();
4174   int mDim=getMeshDimension();
4175   if(spaceDim==3)
4176     {
4177       if(mDim==3)
4178         {
4179           const double *coords=_coords->getConstPointer();
4180           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4181         }
4182       /*else if(mDim==2)
4183         {
4184           
4185         }*/
4186       else
4187         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4188     }
4189   else if(spaceDim==2)
4190     {
4191       if(mDim==2)
4192         {
4193           const double *coords=_coords->getConstPointer();
4194           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4195         }
4196       else
4197         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4198     }
4199   else if(spaceDim==1)
4200     {
4201       if(mDim==1)
4202         {
4203           const double *coords=_coords->getConstPointer();
4204           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4205         }
4206       else
4207         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4208     }
4209   else
4210     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4211 }
4212
4213 /*!
4214  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4215  * least two its edges intersect each other anywhere except their extremities. An
4216  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4217  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4218  *         cleared before filling in.
4219  *  \param [in] eps - precision.
4220  *  \throw If \a this->getMeshDimension() != 2.
4221  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4222  */
4223 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4224 {
4225   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4226   if(getMeshDimension()!=2)
4227     throw INTERP_KERNEL::Exception(msg);
4228   int spaceDim=getSpaceDimension();
4229   if(spaceDim!=2 && spaceDim!=3)
4230     throw INTERP_KERNEL::Exception(msg);
4231   const int *conn=_nodal_connec->getConstPointer();
4232   const int *connI=_nodal_connec_index->getConstPointer();
4233   int nbOfCells=getNumberOfCells();
4234   std::vector<double> cell2DinS2;
4235   for(int i=0;i<nbOfCells;i++)
4236     {
4237       int offset=connI[i];
4238       int nbOfNodesForCell=connI[i+1]-offset-1;
4239       if(nbOfNodesForCell<=3)
4240         continue;
4241       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4242       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4243       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4244         cells.push_back(i);
4245       cell2DinS2.clear();
4246     }
4247 }
4248
4249 /*!
4250  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4251  *
4252  * 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.
4253  * 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.
4254  * 
4255  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4256  * This convex envelop is computed using Jarvis march algorithm.
4257  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4258  * 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)
4259  * 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.
4260  *
4261  * \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.
4262  */
4263 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4264 {
4265   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4267   checkFullyDefined();
4268   const double *coords=getCoords()->getConstPointer();
4269   int nbOfCells=getNumberOfCells();
4270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4271   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4273   int *workIndexOut=nodalConnecIndexOut->getPointer();
4274   *workIndexOut=0;
4275   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4276   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4277   std::set<INTERP_KERNEL::NormalizedCellType> types;
4278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4279   isChanged->alloc(0,1);
4280   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4281     {
4282       int pos=nodalConnecOut->getNumberOfTuples();
4283       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4284         isChanged->pushBackSilent(i);
4285       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4286       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4287     }
4288   if(isChanged->empty())
4289     return 0;
4290   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4291   _types=types;
4292   return isChanged.retn();
4293 }
4294
4295 /*!
4296  * This method is \b NOT const because it can modify \a this.
4297  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4298  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4299  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4300  * \b 1 for translation and rotation around point of 'mesh1D'.
4301  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4302  */
4303 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4304 {
4305   checkFullyDefined();
4306   mesh1D->checkFullyDefined();
4307   if(!mesh1D->isContiguous1D())
4308     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4309   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4310     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4311   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4312     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4313   if(mesh1D->getMeshDimension()!=1)
4314     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4315   bool isQuad=false;
4316   if(isPresenceOfQuadratic())
4317     {
4318       if(mesh1D->isFullyQuadratic())
4319         isQuad=true;
4320       else
4321         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4322     }
4323   zipCoords();
4324   int oldNbOfNodes=getNumberOfNodes();
4325   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4326   switch(policy)
4327     {
4328     case 0:
4329       {
4330         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4331         break;
4332       }
4333     case 1:
4334       {
4335         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4336         break;
4337       }
4338     default:
4339       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4340     }
4341   setCoords(newCoords);
4342   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4343   updateTime();
4344   return ret.retn();
4345 }
4346
4347 /*!
4348  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4349  * If it is not the case an exception will be thrown.
4350  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4351  * intersection of plane defined by ('origin','vec').
4352  * This method has one in/out parameter : 'cut3DCurve'.
4353  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4354  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4355  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4356  * This method will throw an exception if \a this contains a non linear segment.
4357  */
4358 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4359 {
4360   checkFullyDefined();
4361   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4363   int ncells=getNumberOfCells();
4364   int nnodes=getNumberOfNodes();
4365   double vec2[3],vec3[3],vec4[3];
4366   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4367   if(normm<1e-6)
4368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4369   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4370   const int *conn=_nodal_connec->getConstPointer();
4371   const int *connI=_nodal_connec_index->getConstPointer();
4372   const double *coo=_coords->getConstPointer();
4373   std::vector<double> addCoo;
4374   for(int i=0;i<ncells;i++)
4375     {
4376       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4377         {
4378           if(cut3DCurve[i]==-2)
4379             {
4380               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4381               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];
4382               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4383               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4384               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4385                 {
4386                   const double *st2=coo+3*st;
4387                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4388                   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]));
4389                   if(pos>eps && pos<1-eps)
4390                     {
4391                       int nNode=((int)addCoo.size())/3;
4392                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4393                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4394                       cut3DCurve[i]=nnodes+nNode;
4395                     }
4396                 }
4397             }
4398         }
4399       else
4400         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4401     }
4402   if(!addCoo.empty())
4403     {
4404       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4405       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4406       coo2->alloc(newNbOfNodes,3);
4407       double *tmp=coo2->getPointer();
4408       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4409       std::copy(addCoo.begin(),addCoo.end(),tmp);
4410       DataArrayDouble::SetArrayIn(coo2,_coords);
4411     }
4412 }
4413
4414 /*!
4415  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4416  * \param mesh1D is the input 1D mesh used for translation computation.
4417  * \return newCoords new coords filled by this method. 
4418  */
4419 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4420 {
4421   int oldNbOfNodes=getNumberOfNodes();
4422   int nbOf1DCells=mesh1D->getNumberOfCells();
4423   int spaceDim=getSpaceDimension();
4424   DataArrayDouble *ret=DataArrayDouble::New();
4425   std::vector<bool> isQuads;
4426   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4427   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4428   double *retPtr=ret->getPointer();
4429   const double *coords=getCoords()->getConstPointer();
4430   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4431   std::vector<int> v;
4432   std::vector<double> c;
4433   double vec[3];
4434   v.reserve(3);
4435   c.reserve(6);
4436   for(int i=0;i<nbOf1DCells;i++)
4437     {
4438       v.resize(0);
4439       mesh1D->getNodeIdsOfCell(i,v);
4440       c.resize(0);
4441       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4442       mesh1D->getCoordinatesOfNode(v[0],c);
4443       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4444       for(int j=0;j<oldNbOfNodes;j++)
4445         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4446       if(isQuad)
4447         {
4448           c.resize(0);
4449           mesh1D->getCoordinatesOfNode(v[1],c);
4450           mesh1D->getCoordinatesOfNode(v[0],c);
4451           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4452           for(int j=0;j<oldNbOfNodes;j++)
4453             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4454         }
4455     }
4456   ret->copyStringInfoFrom(*getCoords());
4457   return ret;
4458 }
4459
4460 /*!
4461  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4462  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4463  * \return newCoords new coords filled by this method. 
4464  */
4465 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4466 {
4467   if(mesh1D->getSpaceDimension()==2)
4468     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4469   if(mesh1D->getSpaceDimension()==3)
4470     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4471   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4472 }
4473
4474 /*!
4475  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4476  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4477  * \return newCoords new coords filled by this method. 
4478  */
4479 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4480 {
4481   if(isQuad)
4482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4483   int oldNbOfNodes=getNumberOfNodes();
4484   int nbOf1DCells=mesh1D->getNumberOfCells();
4485   if(nbOf1DCells<2)
4486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4487   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4488   int nbOfLevsInVec=nbOf1DCells+1;
4489   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4490   double *retPtr=ret->getPointer();
4491   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4492   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4493   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4494   tmp->setCoords(tmp2);
4495   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4496   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4497   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4498   for(int i=1;i<nbOfLevsInVec;i++)
4499     {
4500       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4501       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4502       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4503       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4504       tmp->translate(vec);
4505       double tmp3[2],radius,alpha,alpha0;
4506       const double *p0=i+1<nbOfLevsInVec?begin:third;
4507       const double *p1=i+1<nbOfLevsInVec?end:begin;
4508       const double *p2=i+1<nbOfLevsInVec?third:end;
4509       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4510       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]);
4511       double angle=acos(cosangle/(radius*radius));
4512       tmp->rotate(end,0,angle);
4513       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4514     }
4515   return ret.retn();
4516 }
4517
4518 /*!
4519  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4520  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4521  * \return newCoords new coords filled by this method. 
4522  */
4523 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4524 {
4525   if(isQuad)
4526     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4527   int oldNbOfNodes=getNumberOfNodes();
4528   int nbOf1DCells=mesh1D->getNumberOfCells();
4529   if(nbOf1DCells<2)
4530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4531   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4532   int nbOfLevsInVec=nbOf1DCells+1;
4533   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4534   double *retPtr=ret->getPointer();
4535   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4536   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4537   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4538   tmp->setCoords(tmp2);
4539   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4540   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4541   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4542   for(int i=1;i<nbOfLevsInVec;i++)
4543     {
4544       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4545       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4546       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4547       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4548       tmp->translate(vec);
4549       double tmp3[2],radius,alpha,alpha0;
4550       const double *p0=i+1<nbOfLevsInVec?begin:third;
4551       const double *p1=i+1<nbOfLevsInVec?end:begin;
4552       const double *p2=i+1<nbOfLevsInVec?third:end;
4553       double vecPlane[3]={
4554         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4555         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4556         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4557       };
4558       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4559       if(norm>1.e-7)
4560         {
4561           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4562           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4563           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4564           double s2=norm2;
4565           double c2=cos(asin(s2));
4566           double m[3][3]={
4567             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4568             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4569             {-vec2[1]*s2, vec2[0]*s2, c2}
4570           };
4571           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]};
4572           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]};
4573           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]};
4574           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4575           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]);
4576           double angle=acos(cosangle/(radius*radius));
4577           tmp->rotate(end,vecPlane,angle);
4578           
4579         }
4580       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4581     }
4582   return ret.retn();
4583 }
4584
4585 /*!
4586  * This method is private because not easy to use for end user. This method is const contrary to
4587  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4588  * the coords sorted slice by slice.
4589  * \param isQuad specifies presence of quadratic cells.
4590  */
4591 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4592 {
4593   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4594   int nbOf2DCells=getNumberOfCells();
4595   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4596   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4597   const int *conn=_nodal_connec->getConstPointer();
4598   const int *connI=_nodal_connec_index->getConstPointer();
4599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4601   newConnI->alloc(nbOf3DCells+1,1);
4602   int *newConnIPtr=newConnI->getPointer();
4603   *newConnIPtr++=0;
4604   std::vector<int> newc;
4605   for(int j=0;j<nbOf2DCells;j++)
4606     {
4607       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4608       *newConnIPtr++=(int)newc.size();
4609     }
4610   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4611   int *newConnPtr=newConn->getPointer();
4612   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4613   newConnIPtr=newConnI->getPointer();
4614   for(int iz=0;iz<nbOf1DCells;iz++)
4615     {
4616       if(iz!=0)
4617         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4618       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4619         {
4620           int icell=(int)(iter-newc.begin());
4621           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4622             {
4623               if(*iter!=-1)
4624                 *newConnPtr=(*iter)+iz*deltaPerLev;
4625               else
4626                 *newConnPtr=-1;
4627             }
4628           else
4629             *newConnPtr=(*iter);
4630         }
4631     }
4632   ret->setConnectivity(newConn,newConnI,true);
4633   ret->setCoords(getCoords());
4634   return ret;
4635 }
4636
4637 /*!
4638  * Checks if \a this mesh is constituted by only quadratic cells.
4639  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4640  *  \throw If the coordinates array is not set.
4641  *  \throw If the nodal connectivity of cells is not defined.
4642  */
4643 bool MEDCouplingUMesh::isFullyQuadratic() const
4644 {
4645   checkFullyDefined();
4646   bool ret=true;
4647   int nbOfCells=getNumberOfCells();
4648   for(int i=0;i<nbOfCells && ret;i++)
4649     {
4650       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4651       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4652       ret=cm.isQuadratic();
4653     }
4654   return ret;
4655 }
4656
4657 /*!
4658  * Checks if \a this mesh includes any quadratic cell.
4659  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4660  *  \throw If the coordinates array is not set.
4661  *  \throw If the nodal connectivity of cells is not defined.
4662  */
4663 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4664 {
4665   checkFullyDefined();
4666   bool ret=false;
4667   int nbOfCells=getNumberOfCells();
4668   for(int i=0;i<nbOfCells && !ret;i++)
4669     {
4670       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4671       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4672       ret=cm.isQuadratic();
4673     }
4674   return ret;
4675 }
4676
4677 /*!
4678  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4679  * this mesh, it remains unchanged.
4680  *  \throw If the coordinates array is not set.
4681  *  \throw If the nodal connectivity of cells is not defined.
4682  */
4683 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4684 {
4685   checkFullyDefined();
4686   int nbOfCells=getNumberOfCells();
4687   int delta=0;
4688   const int *iciptr=_nodal_connec_index->getConstPointer();
4689   for(int i=0;i<nbOfCells;i++)
4690     {
4691       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4692       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4693       if(cm.isQuadratic())
4694         {
4695           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4696           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4697           if(!cml.isDynamic())
4698             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4699           else
4700             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4701         }
4702     }
4703   if(delta==0)
4704     return ;
4705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4707   const int *icptr=_nodal_connec->getConstPointer();
4708   newConn->alloc(getMeshLength()-delta,1);
4709   newConnI->alloc(nbOfCells+1,1);
4710   int *ocptr=newConn->getPointer();
4711   int *ociptr=newConnI->getPointer();
4712   *ociptr=0;
4713   _types.clear();
4714   for(int i=0;i<nbOfCells;i++,ociptr++)
4715     {
4716       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4717       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4718       if(!cm.isQuadratic())
4719         {
4720           _types.insert(type);
4721           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4722           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4723         }
4724       else
4725         {
4726           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4727           _types.insert(typel);
4728           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4729           int newNbOfNodes=cml.getNumberOfNodes();
4730           if(cml.isDynamic())
4731             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4732           *ocptr++=(int)typel;
4733           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4734           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4735         }
4736     }
4737   setConnectivity(newConn,newConnI,false);
4738 }
4739
4740 /*!
4741  * This method converts all linear cell in \a this to quadratic one.
4742  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4743  * 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)
4744  * 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.
4745  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4746  * end of the existing coordinates.
4747  * 
4748  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4749  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4750  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4751  * 
4752  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4753  *
4754  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4755  */
4756 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4757 {
4758   DataArrayInt *conn=0,*connI=0;
4759   DataArrayDouble *coords=0;
4760   std::set<INTERP_KERNEL::NormalizedCellType> types;
4761   checkFullyDefined();
4762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4763   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4764   int meshDim=getMeshDimension();
4765   switch(conversionType)
4766     {
4767     case 0:
4768       switch(meshDim)
4769         {
4770         case 1:
4771           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4772           connSafe=conn; connISafe=connI; coordsSafe=coords;
4773           break;
4774         case 2:
4775           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4776           connSafe=conn; connISafe=connI; coordsSafe=coords;
4777           break;
4778         case 3:
4779           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4780           connSafe=conn; connISafe=connI; coordsSafe=coords;
4781           break;
4782         default:
4783           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4784         }
4785       break;
4786     case 1:
4787       {
4788         switch(meshDim)
4789         {
4790         case 1:
4791           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4792           connSafe=conn; connISafe=connI; coordsSafe=coords;
4793           break;
4794         case 2:
4795           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4796           connSafe=conn; connISafe=connI; coordsSafe=coords;
4797           break;
4798         case 3:
4799           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4800           connSafe=conn; connISafe=connI; coordsSafe=coords;
4801           break;
4802         default:
4803           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4804         }
4805         break;
4806       }
4807     default:
4808       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4809     }
4810   setConnectivity(connSafe,connISafe,false);
4811   _types=types;
4812   setCoords(coordsSafe);
4813   return ret.retn();
4814 }
4815
4816 /*!
4817  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4818  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4819  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4820  */
4821 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4822 {
4823   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4824   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4825   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4827   int nbOfCells=getNumberOfCells();
4828   int nbOfNodes=getNumberOfNodes();
4829   const int *cPtr=_nodal_connec->getConstPointer();
4830   const int *icPtr=_nodal_connec_index->getConstPointer();
4831   int lastVal=0,offset=nbOfNodes;
4832   for(int i=0;i<nbOfCells;i++,icPtr++)
4833     {
4834       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4835       if(type==INTERP_KERNEL::NORM_SEG2)
4836         {
4837           types.insert(INTERP_KERNEL::NORM_SEG3);
4838           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4839           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4840           newConn->pushBackSilent(offset++);
4841           lastVal+=4;
4842           newConnI->pushBackSilent(lastVal);
4843           ret->pushBackSilent(i);
4844         }
4845       else
4846         {
4847           types.insert(type);
4848           lastVal+=(icPtr[1]-icPtr[0]);
4849           newConnI->pushBackSilent(lastVal);
4850           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4851         }
4852     }
4853   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4854   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4855   return ret.retn();
4856 }
4857
4858 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)
4859 {
4860   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4863   //
4864   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4865   DataArrayInt *conn1D=0,*conn1DI=0;
4866   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4867   DataArrayDouble *coordsTmp=0;
4868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4869   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4871   const int *c1DPtr=conn1D->begin();
4872   const int *c1DIPtr=conn1DI->begin();
4873   int nbOfCells=getNumberOfCells();
4874   const int *cPtr=_nodal_connec->getConstPointer();
4875   const int *icPtr=_nodal_connec_index->getConstPointer();
4876   int lastVal=0;
4877   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4878     {
4879       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4880       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4881       if(!cm.isQuadratic())
4882         {
4883           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4884           types.insert(typ2); newConn->pushBackSilent(typ2);
4885           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4886           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4887             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4888           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4889           newConnI->pushBackSilent(lastVal);
4890           ret->pushBackSilent(i);
4891         }
4892       else
4893         {
4894           types.insert(typ);
4895           lastVal+=(icPtr[1]-icPtr[0]);
4896           newConnI->pushBackSilent(lastVal);
4897           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4898         }
4899     }
4900   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4901   return ret.retn();
4902 }
4903
4904 /*!
4905  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4906  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4907  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4908  */
4909 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4910 {
4911   
4912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4913   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4914   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4915 }
4916
4917 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4918 {
4919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4920   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4921   //
4922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4925   //
4926   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4927   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4928   DataArrayInt *conn1D=0,*conn1DI=0;
4929   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4930   DataArrayDouble *coordsTmp=0;
4931   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4932   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4933   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4934   const int *c1DPtr=conn1D->begin();
4935   const int *c1DIPtr=conn1DI->begin();
4936   int nbOfCells=getNumberOfCells();
4937   const int *cPtr=_nodal_connec->getConstPointer();
4938   const int *icPtr=_nodal_connec_index->getConstPointer();
4939   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4940   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4941     {
4942       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4943       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4944       if(!cm.isQuadratic())
4945         {
4946           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4947           types.insert(typ2); newConn->pushBackSilent(typ2);
4948           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4949           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4950             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4951           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4952           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4953           newConnI->pushBackSilent(lastVal);
4954           ret->pushBackSilent(i);
4955         }
4956       else
4957         {
4958           types.insert(typ);
4959           lastVal+=(icPtr[1]-icPtr[0]);
4960           newConnI->pushBackSilent(lastVal);
4961           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4962         }
4963     }
4964   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4965   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4966   return ret.retn();
4967 }
4968
4969 /*!
4970  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4971  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4972  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4973  */
4974 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4975 {
4976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4977   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4978   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4979 }
4980
4981 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4982 {
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4984   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
4985   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
4986   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
4987   //
4988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
4991   //
4992   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4993   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
4994   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
4995   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
4996   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
4997   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
4998   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4999   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5001   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5003   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5004   int nbOfCells=getNumberOfCells();
5005   const int *cPtr=_nodal_connec->getConstPointer();
5006   const int *icPtr=_nodal_connec_index->getConstPointer();
5007   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5008   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5009     {
5010       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5011       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5012       if(!cm.isQuadratic())
5013         {
5014           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5015           if(typ2==INTERP_KERNEL::NORM_ERROR)
5016             {
5017               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5018               throw INTERP_KERNEL::Exception(oss.str().c_str());
5019             }
5020           types.insert(typ2); newConn->pushBackSilent(typ2);
5021           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5022           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5023             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5024           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5025             {
5026               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5027               int tmpPos=newConn->getNumberOfTuples();
5028               newConn->pushBackSilent(nodeId2);
5029               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5030             }
5031           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5032           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5033           newConnI->pushBackSilent(lastVal);
5034           ret->pushBackSilent(i);
5035         }
5036       else
5037         {
5038           types.insert(typ);
5039           lastVal+=(icPtr[1]-icPtr[0]);
5040           newConnI->pushBackSilent(lastVal);
5041           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5042         }
5043     }
5044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5046   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5048   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5049   int *c=newConn->getPointer();
5050   const int *cI(newConnI->begin());
5051   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5052     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5053   offset=coordsTmp2Safe->getNumberOfTuples();
5054   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5055     c[cI[(*elt)+1]-1]+=offset;
5056   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5057   return ret.retn();
5058 }
5059
5060 /*!
5061  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5062  * so that the number of cells remains the same. Quadratic faces are converted to
5063  * polygons. This method works only for 2D meshes in
5064  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5065  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5066  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5067  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5068  *         a polylinized edge constituting the input polygon.
5069  *  \throw If the coordinates array is not set.
5070  *  \throw If the nodal connectivity of cells is not defined.
5071  *  \throw If \a this->getMeshDimension() != 2.
5072  *  \throw If \a this->getSpaceDimension() != 2.
5073  */
5074 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5075 {
5076   checkFullyDefined();
5077   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5079   double epsa=fabs(eps);
5080   if(epsa<std::numeric_limits<double>::min())
5081     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 !");
5082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5086   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5087   revDesc1=0; revDescIndx1=0;
5088   mDesc->tessellate2DCurve(eps);
5089   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5090   setCoords(mDesc->getCoords());
5091 }
5092
5093 /*!
5094  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5095  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5096  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5097  *         a sub-divided edge.
5098  *  \throw If the coordinates array is not set.
5099  *  \throw If the nodal connectivity of cells is not defined.
5100  *  \throw If \a this->getMeshDimension() != 1.
5101  *  \throw If \a this->getSpaceDimension() != 2.
5102  */
5103 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5104 {
5105   checkFullyDefined();
5106   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5108   double epsa=fabs(eps);
5109   if(epsa<std::numeric_limits<double>::min())
5110     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 !");
5111   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5112   int nbCells=getNumberOfCells();
5113   int nbNodes=getNumberOfNodes();
5114   const int *conn=_nodal_connec->getConstPointer();
5115   const int *connI=_nodal_connec_index->getConstPointer();
5116   const double *coords=_coords->getConstPointer();
5117   std::vector<double> addCoo;
5118   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5120   newConnI->alloc(nbCells+1,1);
5121   int *newConnIPtr=newConnI->getPointer();
5122   *newConnIPtr=0;
5123   int tmp1[3];
5124   INTERP_KERNEL::Node *tmp2[3];
5125   std::set<INTERP_KERNEL::NormalizedCellType> types;
5126   for(int i=0;i<nbCells;i++,newConnIPtr++)
5127     {
5128       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5129       if(cm.isQuadratic())
5130         {//assert(connI[i+1]-connI[i]-1==3)
5131           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5132           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5133           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5134           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5135           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5136           if(eac)
5137             {
5138               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5139               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5140               delete eac;
5141               newConnIPtr[1]=(int)newConn.size();
5142             }
5143           else
5144             {
5145               types.insert(INTERP_KERNEL::NORM_SEG2);
5146               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5147               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5148               newConnIPtr[1]=newConnIPtr[0]+3;
5149             }
5150         }
5151       else
5152         {
5153           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5154           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5155           newConnIPtr[1]=newConnIPtr[0]+3;
5156         }
5157     }
5158   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5159     return ;
5160   _types=types;
5161   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5163   newConnArr->alloc((int)newConn.size(),1);
5164   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5165   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5166   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5167   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5168   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5169   std::copy(addCoo.begin(),addCoo.end(),work);
5170   DataArrayDouble::SetArrayIn(newCoords,_coords);
5171   updateTime();
5172 }
5173
5174 /*!
5175  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5176  * In addition, returns an array mapping new cells to old ones. <br>
5177  * This method typically increases the number of cells in \a this mesh
5178  * but the number of nodes remains \b unchanged.
5179  * That's why the 3D splitting policies
5180  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5181  *  \param [in] policy - specifies a pattern used for splitting.
5182  * The semantic of \a policy is:
5183  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5184  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5185  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5186  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5187  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5188  *          an id of old cell producing it. The caller is to delete this array using
5189  *         decrRef() as it is no more needed. 
5190  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5191  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5192  *          and \a this->getMeshDimension() != 3. 
5193  *  \throw If \a policy is not one of the four discussed above.
5194  *  \throw If the nodal connectivity of cells is not defined.
5195  */
5196 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5197 {
5198   switch(policy)
5199     {
5200     case 0:
5201       return simplexizePol0();
5202     case 1:
5203       return simplexizePol1();
5204     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5205       return simplexizePlanarFace5();
5206     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5207       return simplexizePlanarFace6();
5208     default:
5209       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)");
5210     }
5211 }
5212
5213 /*!
5214  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5215  * - 1D: INTERP_KERNEL::NORM_SEG2
5216  * - 2D: INTERP_KERNEL::NORM_TRI3
5217  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5218  *
5219  * This method is useful for users that need to use P1 field services as
5220  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5221  * All these methods need mesh support containing only simplex cells.
5222  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5223  *  \throw If the coordinates array is not set.
5224  *  \throw If the nodal connectivity of cells is not defined.
5225  *  \throw If \a this->getMeshDimension() < 1.
5226  */
5227 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5228 {
5229   checkFullyDefined();
5230   int mdim=getMeshDimension();
5231   if(mdim<1 || mdim>3)
5232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5233   int nbCells=getNumberOfCells();
5234   const int *conn=_nodal_connec->getConstPointer();
5235   const int *connI=_nodal_connec_index->getConstPointer();
5236   for(int i=0;i<nbCells;i++)
5237     {
5238       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5239       if(!cm.isSimplex())
5240         return false;
5241     }
5242   return true;
5243 }
5244
5245 /*!
5246  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5247  */
5248 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5249 {
5250   checkConnectivityFullyDefined();
5251   if(getMeshDimension()!=2)
5252     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5253   int nbOfCells=getNumberOfCells();
5254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5255   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5256   ret->alloc(nbOfCells+nbOfCutCells,1);
5257   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5258   int *retPt=ret->getPointer();
5259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5261   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5262   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5263   int *pt=newConn->getPointer();
5264   int *ptI=newConnI->getPointer();
5265   ptI[0]=0;
5266   const int *oldc=_nodal_connec->getConstPointer();
5267   const int *ci=_nodal_connec_index->getConstPointer();
5268   for(int i=0;i<nbOfCells;i++,ci++)
5269     {
5270       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5271         {
5272           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5273                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5274           pt=std::copy(tmp,tmp+8,pt);
5275           ptI[1]=ptI[0]+4;
5276           ptI[2]=ptI[0]+8;
5277           *retPt++=i;
5278           *retPt++=i;
5279           ptI+=2;
5280         }
5281       else
5282         {
5283           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5284           ptI[1]=ptI[0]+ci[1]-ci[0];
5285           ptI++;
5286           *retPt++=i;
5287         }
5288     }
5289   _nodal_connec->decrRef();
5290   _nodal_connec=newConn.retn();
5291   _nodal_connec_index->decrRef();
5292   _nodal_connec_index=newConnI.retn();
5293   computeTypes();
5294   updateTime();
5295   return ret.retn();
5296 }
5297
5298 /*!
5299  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5300  */
5301 DataArrayInt *MEDCouplingUMesh::simplexizePol1() 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]+4],
5326                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],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 INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5353  */
5354 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5355 {
5356   checkConnectivityFullyDefined();
5357   if(getMeshDimension()!=3)
5358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5359   int nbOfCells=getNumberOfCells();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5361   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5362   ret->alloc(nbOfCells+4*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+4*nbOfCutCells+1,1);
5368   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
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_HEXA8)
5377         {
5378           for(int j=0;j<5;j++,pt+=5,ptI++)
5379             {
5380               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5381               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];
5382               *retPt++=i;
5383               ptI[1]=ptI[0]+5;
5384             }
5385         }
5386       else
5387         {
5388           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5389           ptI[1]=ptI[0]+ci[1]-ci[0];
5390           ptI++;
5391           *retPt++=i;
5392         }
5393     }
5394   _nodal_connec->decrRef();
5395   _nodal_connec=newConn.retn();
5396   _nodal_connec_index->decrRef();
5397   _nodal_connec_index=newConnI.retn();
5398   computeTypes();
5399   updateTime();
5400   return ret.retn();
5401 }
5402
5403 /*!
5404  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5405  */
5406 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5407 {
5408   checkConnectivityFullyDefined();
5409   if(getMeshDimension()!=3)
5410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5411   int nbOfCells=getNumberOfCells();
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5413   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5414   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5415   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5416   int *retPt=ret->getPointer();
5417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5419   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5420   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5421   int *pt=newConn->getPointer();
5422   int *ptI=newConnI->getPointer();
5423   ptI[0]=0;
5424   const int *oldc=_nodal_connec->getConstPointer();
5425   const int *ci=_nodal_connec_index->getConstPointer();
5426   for(int i=0;i<nbOfCells;i++,ci++)
5427     {
5428       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5429         {
5430           for(int j=0;j<6;j++,pt+=5,ptI++)
5431             {
5432               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5433               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];
5434               *retPt++=i;
5435               ptI[1]=ptI[0]+5;
5436             }
5437         }
5438       else
5439         {
5440           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5441           ptI[1]=ptI[0]+ci[1]-ci[0];
5442           ptI++;
5443           *retPt++=i;
5444         }
5445     }
5446   _nodal_connec->decrRef();
5447   _nodal_connec=newConn.retn();
5448   _nodal_connec_index->decrRef();
5449   _nodal_connec_index=newConnI.retn();
5450   computeTypes();
5451   updateTime();
5452   return ret.retn();
5453 }
5454
5455 /*!
5456  * 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.
5457  * This method completly ignore coordinates.
5458  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5459  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5460  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5461  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5462  */
5463 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5464 {
5465   checkFullyDefined();
5466   if(getMeshDimension()!=2)
5467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5468   int nbOfCells=getNumberOfCells();
5469   int *connI=_nodal_connec_index->getPointer();
5470   int newConnLgth=0;
5471   for(int i=0;i<nbOfCells;i++,connI++)
5472     {
5473       int offset=descIndex[i];
5474       int nbOfEdges=descIndex[i+1]-offset;
5475       //
5476       bool ddirect=desc[offset+nbOfEdges-1]>0;
5477       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5478       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5479       for(int j=0;j<nbOfEdges;j++)
5480         {
5481           bool direct=desc[offset+j]>0;
5482           int edgeId=std::abs(desc[offset+j])-1;
5483           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5484             {
5485               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5486               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5487               int ref2=direct?id1:id2;
5488               if(ref==ref2)
5489                 {
5490                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5491                   newConnLgth+=nbOfSubNodes-1;
5492                   ref=direct?id2:id1;
5493                 }
5494               else
5495                 {
5496                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5497                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5498                 }
5499             }
5500           else
5501             {
5502               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5503             }
5504         }
5505       newConnLgth++;//+1 is for cell type
5506       connI[1]=newConnLgth;
5507     }
5508   //
5509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5510   newConn->alloc(newConnLgth,1);
5511   int *work=newConn->getPointer();
5512   for(int i=0;i<nbOfCells;i++)
5513     {
5514       *work++=INTERP_KERNEL::NORM_POLYGON;
5515       int offset=descIndex[i];
5516       int nbOfEdges=descIndex[i+1]-offset;
5517       for(int j=0;j<nbOfEdges;j++)
5518         {
5519           bool direct=desc[offset+j]>0;
5520           int edgeId=std::abs(desc[offset+j])-1;
5521           if(direct)
5522             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5523           else
5524             {
5525               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5526               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5527               work=std::copy(it,it+nbOfSubNodes-1,work);
5528             }
5529         }
5530     }
5531   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5532   _types.clear();
5533   if(nbOfCells>0)
5534     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5535 }
5536
5537 /*!
5538  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5539  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5540  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5541  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5542  * so it can be useful to call mergeNodes() before calling this method.
5543  *  \throw If \a this->getMeshDimension() <= 1.
5544  *  \throw If the coordinates array is not set.
5545  *  \throw If the nodal connectivity of cells is not defined.
5546  */
5547 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5548 {
5549   checkFullyDefined();
5550   if(getMeshDimension()<=1)
5551     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5552   int nbOfCells=getNumberOfCells();
5553   if(nbOfCells<1)
5554     return ;
5555   int initMeshLgth=getMeshLength();
5556   int *conn=_nodal_connec->getPointer();
5557   int *index=_nodal_connec_index->getPointer();
5558   int posOfCurCell=0;
5559   int newPos=0;
5560   int lgthOfCurCell;
5561   for(int i=0;i<nbOfCells;i++)
5562     {
5563       lgthOfCurCell=index[i+1]-posOfCurCell;
5564       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5565       int newLgth;
5566       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5567                                                                                                      conn+newPos+1,newLgth);
5568       conn[newPos]=newType;
5569       newPos+=newLgth+1;
5570       posOfCurCell=index[i+1];
5571       index[i+1]=newPos;
5572     }
5573   if(newPos!=initMeshLgth)
5574     _nodal_connec->reAlloc(newPos);
5575   computeTypes();
5576 }
5577
5578 /*!
5579  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5580  * A cell is considered to be oriented correctly if an angle between its
5581  * normal vector and a given vector is less than \c PI / \c 2.
5582  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5583  *         cells. 
5584  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5585  *         checked.
5586  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5587  *         is not cleared before filling in.
5588  *  \throw If \a this->getMeshDimension() != 2.
5589  *  \throw If \a this->getSpaceDimension() != 3.
5590  *
5591  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5592  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5593  */
5594 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5595 {
5596   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5597     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5598   int nbOfCells=getNumberOfCells();
5599   const int *conn=_nodal_connec->getConstPointer();
5600   const int *connI=_nodal_connec_index->getConstPointer();
5601   const double *coordsPtr=_coords->getConstPointer();
5602   for(int i=0;i<nbOfCells;i++)
5603     {
5604       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5605       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5606         {
5607           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5608           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5609             cells.push_back(i);
5610         }
5611     }
5612 }
5613
5614 /*!
5615  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5616  * considered to be oriented correctly if an angle between its normal vector and a
5617  * given vector is less than \c PI / \c 2. 
5618  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5619  *         cells. 
5620  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5621  *         checked.
5622  *  \throw If \a this->getMeshDimension() != 2.
5623  *  \throw If \a this->getSpaceDimension() != 3.
5624  *
5625  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5626  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5627  */
5628 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5629 {
5630   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5631     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5632   int nbOfCells=getNumberOfCells();
5633   int *conn=_nodal_connec->getPointer();
5634   const int *connI=_nodal_connec_index->getConstPointer();
5635   const double *coordsPtr=_coords->getConstPointer();
5636   bool isModified=false;
5637   for(int i=0;i<nbOfCells;i++)
5638     {
5639       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5640       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5641         {
5642           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5643           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5644             {
5645               isModified=true;
5646               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5647               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5648               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5649             }
5650         }
5651     }
5652   if(isModified)
5653     _nodal_connec->declareAsNew();
5654   updateTime();
5655 }
5656
5657 /*!
5658  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5659  * oriented facets. The normal vector of the facet should point out of the cell.
5660  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5661  *         is not cleared before filling in.
5662  *  \throw If \a this->getMeshDimension() != 3.
5663  *  \throw If \a this->getSpaceDimension() != 3.
5664  *  \throw If the coordinates array is not set.
5665  *  \throw If the nodal connectivity of cells is not defined.
5666  *
5667  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5668  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5669  */
5670 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5671 {
5672   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5673     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5674   int nbOfCells=getNumberOfCells();
5675   const int *conn=_nodal_connec->getConstPointer();
5676   const int *connI=_nodal_connec_index->getConstPointer();
5677   const double *coordsPtr=_coords->getConstPointer();
5678   for(int i=0;i<nbOfCells;i++)
5679     {
5680       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5681       if(type==INTERP_KERNEL::NORM_POLYHED)
5682         {
5683           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5684             cells.push_back(i);
5685         }
5686     }
5687 }
5688
5689 /*!
5690  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5691  * out of the cell. 
5692  *  \throw If \a this->getMeshDimension() != 3.
5693  *  \throw If \a this->getSpaceDimension() != 3.
5694  *  \throw If the coordinates array is not set.
5695  *  \throw If the nodal connectivity of cells is not defined.
5696  *  \throw If the reparation fails.
5697  *
5698  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5699  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5700  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5701  */
5702 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5703 {
5704   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5705     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5706   int nbOfCells=getNumberOfCells();
5707   int *conn=_nodal_connec->getPointer();
5708   const int *connI=_nodal_connec_index->getConstPointer();
5709   const double *coordsPtr=_coords->getConstPointer();
5710   for(int i=0;i<nbOfCells;i++)
5711     {
5712       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5713       if(type==INTERP_KERNEL::NORM_POLYHED)
5714         {
5715           try
5716             {
5717               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5718                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5719             }
5720           catch(INTERP_KERNEL::Exception& e)
5721             {
5722               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5723               throw INTERP_KERNEL::Exception(oss.str().c_str());
5724             }
5725         }
5726     }
5727   updateTime();
5728 }
5729
5730 /*!
5731  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5732  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5733  * according to which the first facet of the cell should be oriented to have the normal vector
5734  * pointing out of cell.
5735  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5736  *         cells. The caller is to delete this array using decrRef() as it is no more
5737  *         needed. 
5738  *  \throw If \a this->getMeshDimension() != 3.
5739  *  \throw If \a this->getSpaceDimension() != 3.
5740  *  \throw If the coordinates array is not set.
5741  *  \throw If the nodal connectivity of cells is not defined.
5742  *
5743  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5744  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5745  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5746  */
5747 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5748 {
5749   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5750   if(getMeshDimension()!=3)
5751     throw INTERP_KERNEL::Exception(msg);
5752   int spaceDim=getSpaceDimension();
5753   if(spaceDim!=3)
5754     throw INTERP_KERNEL::Exception(msg);
5755   //
5756   int nbOfCells=getNumberOfCells();
5757   int *conn=_nodal_connec->getPointer();
5758   const int *connI=_nodal_connec_index->getConstPointer();
5759   const double *coo=getCoords()->getConstPointer();
5760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5761   for(int i=0;i<nbOfCells;i++)
5762     {
5763       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5764       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5765         {
5766           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5767             {
5768               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5769               cells->pushBackSilent(i);
5770             }
5771         }
5772     }
5773   return cells.retn();
5774 }
5775
5776 /*!
5777  * This method is a faster method to correct orientation of all 3D cells in \a this.
5778  * 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.
5779  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5780  * 
5781  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5782  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5783  */
5784 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5785 {
5786   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5787     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5788   int nbOfCells=getNumberOfCells();
5789   int *conn=_nodal_connec->getPointer();
5790   const int *connI=_nodal_connec_index->getConstPointer();
5791   const double *coordsPtr=_coords->getConstPointer();
5792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5793   for(int i=0;i<nbOfCells;i++)
5794     {
5795       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5796       switch(type)
5797         {
5798         case INTERP_KERNEL::NORM_TETRA4:
5799           {
5800             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5801               {
5802                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5803                 ret->pushBackSilent(i);
5804               }
5805             break;
5806           }
5807         case INTERP_KERNEL::NORM_PYRA5:
5808           {
5809             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5810               {
5811                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5812                 ret->pushBackSilent(i);
5813               }
5814             break;
5815           }
5816         case INTERP_KERNEL::NORM_PENTA6:
5817         case INTERP_KERNEL::NORM_HEXA8:
5818         case INTERP_KERNEL::NORM_HEXGP12:
5819           {
5820             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5821               {
5822                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5823                 ret->pushBackSilent(i);
5824               }
5825             break;
5826           }
5827         case INTERP_KERNEL::NORM_POLYHED:
5828           {
5829             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5830               {
5831                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5832                 ret->pushBackSilent(i);
5833               }
5834             break;
5835           }
5836         default:
5837           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 !");
5838         }
5839     }
5840   updateTime();
5841   return ret.retn();
5842 }
5843
5844 /*!
5845  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5846  * If it is not the case an exception will be thrown.
5847  * This method is fast because the first cell of \a this is used to compute the plane.
5848  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5849  * \param pos output of size at least 3 used to store a point owned of searched plane.
5850  */
5851 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5852 {
5853   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5854     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5855   const int *conn=_nodal_connec->getConstPointer();
5856   const int *connI=_nodal_connec_index->getConstPointer();
5857   const double *coordsPtr=_coords->getConstPointer();
5858   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5859   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5860 }
5861
5862 /*!
5863  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5864  * cells. Currently cells of the following types are treated:
5865  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5866  * For a cell of other type an exception is thrown.
5867  * Space dimension of a 2D mesh can be either 2 or 3.
5868  * The Edge Ratio of a cell \f$t\f$ is: 
5869  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5870  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5871  *  the smallest edge lengths of \f$t\f$.
5872  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5873  *          cells and one time, lying on \a this mesh. The caller is to delete this
5874  *          field using decrRef() as it is no more needed. 
5875  *  \throw If the coordinates array is not set.
5876  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5877  *  \throw If the connectivity data array has more than one component.
5878  *  \throw If the connectivity data array has a named component.
5879  *  \throw If the connectivity index data array has more than one component.
5880  *  \throw If the connectivity index data array has a named component.
5881  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5882  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5883  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5884  */
5885 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5886 {
5887   checkCoherency();
5888   int spaceDim=getSpaceDimension();
5889   int meshDim=getMeshDimension();
5890   if(spaceDim!=2 && spaceDim!=3)
5891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5892   if(meshDim!=2 && meshDim!=3)
5893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5894   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5895   ret->setMesh(this);
5896   int nbOfCells=getNumberOfCells();
5897   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5898   arr->alloc(nbOfCells,1);
5899   double *pt=arr->getPointer();
5900   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5901   const int *conn=_nodal_connec->getConstPointer();
5902   const int *connI=_nodal_connec_index->getConstPointer();
5903   const double *coo=_coords->getConstPointer();
5904   double tmp[12];
5905   for(int i=0;i<nbOfCells;i++,pt++)
5906     {
5907       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5908       switch(t)
5909         {
5910           case INTERP_KERNEL::NORM_TRI3:
5911             {
5912               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5913               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5914               break;
5915             }
5916           case INTERP_KERNEL::NORM_QUAD4:
5917             {
5918               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5919               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5920               break;
5921             }
5922           case INTERP_KERNEL::NORM_TETRA4:
5923             {
5924               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5925               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5926               break;
5927             }
5928         default:
5929           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5930         }
5931       conn+=connI[i+1]-connI[i];
5932     }
5933   ret->setName("EdgeRatio");
5934   ret->synchronizeTimeWithSupport();
5935   return ret.retn();
5936 }
5937
5938 /*!
5939  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5940  * cells. Currently cells of the following types are treated:
5941  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5942  * For a cell of other type an exception is thrown.
5943  * Space dimension of a 2D mesh can be either 2 or 3.
5944  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5945  *          cells and one time, lying on \a this mesh. The caller is to delete this
5946  *          field using decrRef() as it is no more needed. 
5947  *  \throw If the coordinates array is not set.
5948  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5949  *  \throw If the connectivity data array has more than one component.
5950  *  \throw If the connectivity data array has a named component.
5951  *  \throw If the connectivity index data array has more than one component.
5952  *  \throw If the connectivity index data array has a named component.
5953  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5954  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5955  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5956  */
5957 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5958 {
5959   checkCoherency();
5960   int spaceDim=getSpaceDimension();
5961   int meshDim=getMeshDimension();
5962   if(spaceDim!=2 && spaceDim!=3)
5963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5964   if(meshDim!=2 && meshDim!=3)
5965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5966   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5967   ret->setMesh(this);
5968   int nbOfCells=getNumberOfCells();
5969   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5970   arr->alloc(nbOfCells,1);
5971   double *pt=arr->getPointer();
5972   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5973   const int *conn=_nodal_connec->getConstPointer();
5974   const int *connI=_nodal_connec_index->getConstPointer();
5975   const double *coo=_coords->getConstPointer();
5976   double tmp[12];
5977   for(int i=0;i<nbOfCells;i++,pt++)
5978     {
5979       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5980       switch(t)
5981         {
5982           case INTERP_KERNEL::NORM_TRI3:
5983             {
5984               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5985               *pt=INTERP_KERNEL::triAspectRatio(tmp);
5986               break;
5987             }
5988           case INTERP_KERNEL::NORM_QUAD4:
5989             {
5990               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5991               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5992               break;
5993             }
5994           case INTERP_KERNEL::NORM_TETRA4:
5995             {
5996               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5997               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5998               break;
5999             }
6000         default:
6001           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6002         }
6003       conn+=connI[i+1]-connI[i];
6004     }
6005   ret->setName("AspectRatio");
6006   ret->synchronizeTimeWithSupport();
6007   return ret.retn();
6008 }
6009
6010 /*!
6011  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6012  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6013  * treated: INTERP_KERNEL::NORM_QUAD4.
6014  * For a cell of other type an exception is thrown.
6015  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6016  *          cells and one time, lying on \a this mesh. The caller is to delete this
6017  *          field using decrRef() as it is no more needed. 
6018  *  \throw If the coordinates array is not set.
6019  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6020  *  \throw If the connectivity data array has more than one component.
6021  *  \throw If the connectivity data array has a named component.
6022  *  \throw If the connectivity index data array has more than one component.
6023  *  \throw If the connectivity index data array has a named component.
6024  *  \throw If \a this->getMeshDimension() != 2.
6025  *  \throw If \a this->getSpaceDimension() != 3.
6026  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6027  */
6028 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6029 {
6030   checkCoherency();
6031   int spaceDim=getSpaceDimension();
6032   int meshDim=getMeshDimension();
6033   if(spaceDim!=3)
6034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6035   if(meshDim!=2)
6036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6037   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6038   ret->setMesh(this);
6039   int nbOfCells=getNumberOfCells();
6040   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6041   arr->alloc(nbOfCells,1);
6042   double *pt=arr->getPointer();
6043   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6044   const int *conn=_nodal_connec->getConstPointer();
6045   const int *connI=_nodal_connec_index->getConstPointer();
6046   const double *coo=_coords->getConstPointer();
6047   double tmp[12];
6048   for(int i=0;i<nbOfCells;i++,pt++)
6049     {
6050       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6051       switch(t)
6052         {
6053           case INTERP_KERNEL::NORM_QUAD4:
6054             {
6055               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6056               *pt=INTERP_KERNEL::quadWarp(tmp);
6057               break;
6058             }
6059         default:
6060           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6061         }
6062       conn+=connI[i+1]-connI[i];
6063     }
6064   ret->setName("Warp");
6065   ret->synchronizeTimeWithSupport();
6066   return ret.retn();
6067 }
6068
6069
6070 /*!
6071  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6072  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6073  * treated: INTERP_KERNEL::NORM_QUAD4.
6074  * For a cell of other type an exception is thrown.
6075  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6076  *          cells and one time, lying on \a this mesh. The caller is to delete this
6077  *          field using decrRef() as it is no more needed. 
6078  *  \throw If the coordinates array is not set.
6079  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6080  *  \throw If the connectivity data array has more than one component.
6081  *  \throw If the connectivity data array has a named component.
6082  *  \throw If the connectivity index data array has more than one component.
6083  *  \throw If the connectivity index data array has a named component.
6084  *  \throw If \a this->getMeshDimension() != 2.
6085  *  \throw If \a this->getSpaceDimension() != 3.
6086  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6087  */
6088 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6089 {
6090   checkCoherency();
6091   int spaceDim=getSpaceDimension();
6092   int meshDim=getMeshDimension();
6093   if(spaceDim!=3)
6094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6095   if(meshDim!=2)
6096     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6097   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6098   ret->setMesh(this);
6099   int nbOfCells=getNumberOfCells();
6100   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6101   arr->alloc(nbOfCells,1);
6102   double *pt=arr->getPointer();
6103   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6104   const int *conn=_nodal_connec->getConstPointer();
6105   const int *connI=_nodal_connec_index->getConstPointer();
6106   const double *coo=_coords->getConstPointer();
6107   double tmp[12];
6108   for(int i=0;i<nbOfCells;i++,pt++)
6109     {
6110       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6111       switch(t)
6112         {
6113           case INTERP_KERNEL::NORM_QUAD4:
6114             {
6115               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6116               *pt=INTERP_KERNEL::quadSkew(tmp);
6117               break;
6118             }
6119         default:
6120           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6121         }
6122       conn+=connI[i+1]-connI[i];
6123     }
6124   ret->setName("Skew");
6125   ret->synchronizeTimeWithSupport();
6126   return ret.retn();
6127 }
6128
6129 /*!
6130  * This method aggregate the bbox of each cell and put it into bbox parameter.
6131  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6132  */
6133 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6134 {
6135   int spaceDim=getSpaceDimension();
6136   int nbOfCells=getNumberOfCells();
6137   bbox.resize(2*nbOfCells*spaceDim);
6138   for(int i=0;i<nbOfCells*spaceDim;i++)
6139     {
6140       bbox[2*i]=std::numeric_limits<double>::max();
6141       bbox[2*i+1]=-std::numeric_limits<double>::max();
6142     }
6143   const double *coordsPtr=_coords->getConstPointer();
6144   const int *conn=_nodal_connec->getConstPointer();
6145   const int *connI=_nodal_connec_index->getConstPointer();
6146   for(int i=0;i<nbOfCells;i++)
6147     {
6148       int offset=connI[i]+1;
6149       int nbOfNodesForCell=connI[i+1]-offset;
6150       for(int j=0;j<nbOfNodesForCell;j++)
6151         {
6152           int nodeId=conn[offset+j];
6153           if(nodeId>=0)
6154             for(int k=0;k<spaceDim;k++)
6155               {
6156                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6157                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6158               }
6159         }
6160     }
6161 }
6162
6163 /// @cond INTERNAL
6164
6165 namespace ParaMEDMEMImpl
6166 {
6167   class ConnReader
6168   {
6169   public:
6170     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6171     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6172   private:
6173     const int *_conn;
6174     int _val;
6175   };
6176
6177   class ConnReader2
6178   {
6179   public:
6180     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6181     bool operator() (const int& pos) { return _conn[pos]==_val; }
6182   private:
6183     const int *_conn;
6184     int _val;
6185   };
6186 }
6187
6188 /// @endcond
6189
6190 /*!
6191  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6192  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6193  * \a this is composed in cell types.
6194  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6195  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6196  * This parameter is kept only for compatibility with other methode listed above.
6197  */
6198 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6199 {
6200   checkConnectivityFullyDefined();
6201   const int *conn=_nodal_connec->getConstPointer();
6202   const int *connI=_nodal_connec_index->getConstPointer();
6203   const int *work=connI;
6204   int nbOfCells=getNumberOfCells();
6205   std::size_t n=getAllTypes().size();
6206   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6207   std::set<INTERP_KERNEL::NormalizedCellType> types;
6208   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6209     {
6210       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6211       if(types.find(typ)!=types.end())
6212         {
6213           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6214           oss << " is not contiguous !";
6215           throw INTERP_KERNEL::Exception(oss.str().c_str());
6216         }
6217       types.insert(typ);
6218       ret[3*i]=typ;
6219       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6220       ret[3*i+1]=(int)std::distance(work,work2);
6221       work=work2;
6222     }
6223   return ret;
6224 }
6225
6226 /*!
6227  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6228  * only for types cell, type node is not managed.
6229  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6230  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6231  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6232  * If 2 or more same geometric type is in \a code and exception is thrown too.
6233  *
6234  * This method firstly checks
6235  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6236  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6237  * an exception is thrown too.
6238  * 
6239  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6240  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6241  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6242  */
6243 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6244 {
6245   if(code.empty())
6246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6247   std::size_t sz=code.size();
6248   std::size_t n=sz/3;
6249   if(sz%3!=0)
6250     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6251   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6252   int nb=0;
6253   bool isNoPflUsed=true;
6254   for(std::size_t i=0;i<n;i++)
6255     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6256       {
6257         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6258         nb+=code[3*i+1];
6259         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6260           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6261         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6262       }
6263   if(types.size()!=n)
6264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6265   if(isNoPflUsed)
6266     {
6267       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6268         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6269       if(types.size()==_types.size())
6270         return 0;
6271     }
6272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6273   ret->alloc(nb,1);
6274   int *retPtr=ret->getPointer();
6275   const int *connI=_nodal_connec_index->getConstPointer();
6276   const int *conn=_nodal_connec->getConstPointer();
6277   int nbOfCells=getNumberOfCells();
6278   const int *i=connI;
6279   int kk=0;
6280   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6281     {
6282       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6283       int offset=(int)std::distance(connI,i);
6284       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6285       int nbOfCellsOfCurType=(int)std::distance(i,j);
6286       if(code[3*kk+2]==-1)
6287         for(int k=0;k<nbOfCellsOfCurType;k++)
6288           *retPtr++=k+offset;
6289       else
6290         {
6291           int idInIdsPerType=code[3*kk+2];
6292           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6293             {
6294               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6295               if(zePfl)
6296                 {
6297                   zePfl->checkAllocated();
6298                   if(zePfl->getNumberOfComponents()==1)
6299                     {
6300                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6301                         {
6302                           if(*k>=0 && *k<nbOfCellsOfCurType)
6303                             *retPtr=(*k)+offset;
6304                           else
6305                             {
6306                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6307                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6308                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6309                             }
6310                         }
6311                     }
6312                   else
6313                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6314                 }
6315               else
6316                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6317             }
6318           else
6319             {
6320               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6321               oss << " should be in [0," << idsPerType.size() << ") !";
6322               throw INTERP_KERNEL::Exception(oss.str().c_str());
6323             }
6324         }
6325       i=j;
6326     }
6327   return ret.retn();
6328 }
6329
6330 /*!
6331  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6332  * 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.
6333  * 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.
6334  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6335  * 
6336  * \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.
6337  * \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,
6338  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6339  * \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.
6340  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6341  * \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
6342  */
6343 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6344 {
6345   if(!profile)
6346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6347   if(profile->getNumberOfComponents()!=1)
6348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6349   checkConnectivityFullyDefined();
6350   const int *conn=_nodal_connec->getConstPointer();
6351   const int *connI=_nodal_connec_index->getConstPointer();
6352   int nbOfCells=getNumberOfCells();
6353   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6354   std::vector<int> typeRangeVals(1);
6355   for(const int *i=connI;i!=connI+nbOfCells;)
6356     {
6357       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6358       if(std::find(types.begin(),types.end(),curType)!=types.end())
6359         {
6360           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6361         }
6362       types.push_back(curType);
6363       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6364       typeRangeVals.push_back((int)std::distance(connI,i));
6365     }
6366   //
6367   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6368   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6372   //
6373   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6374   code.resize(3*nbOfCastsFinal);
6375   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6376   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6377   for(int i=0;i<nbOfCastsFinal;i++)
6378     {
6379       int castId=castsPresent->getIJ(i,0);
6380       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6381       idsInPflPerType2.push_back(tmp3);
6382       code[3*i]=(int)types[castId];
6383       code[3*i+1]=tmp3->getNumberOfTuples();
6384       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6385       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6386         {
6387           tmp4->copyStringInfoFrom(*profile);
6388           idsPerType2.push_back(tmp4);
6389           code[3*i+2]=(int)idsPerType2.size()-1;
6390         }
6391       else
6392         {
6393           code[3*i+2]=-1;
6394         }
6395     }
6396   std::size_t sz2=idsInPflPerType2.size();
6397   idsInPflPerType.resize(sz2);
6398   for(std::size_t i=0;i<sz2;i++)
6399     {
6400       DataArrayInt *locDa=idsInPflPerType2[i];
6401       locDa->incrRef();
6402       idsInPflPerType[i]=locDa;
6403     }
6404   std::size_t sz=idsPerType2.size();
6405   idsPerType.resize(sz);
6406   for(std::size_t i=0;i<sz;i++)
6407     {
6408       DataArrayInt *locDa=idsPerType2[i];
6409       locDa->incrRef();
6410       idsPerType[i]=locDa;
6411     }
6412 }
6413
6414 /*!
6415  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6416  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6417  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6418  * 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.
6419  */
6420 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6421 {
6422   checkFullyDefined();
6423   nM1LevMesh->checkFullyDefined();
6424   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6426   if(_coords!=nM1LevMesh->getCoords())
6427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6430   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6432   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6434   tmp->setConnectivity(tmp0,tmp1);
6435   tmp->renumberCells(ret0->getConstPointer(),false);
6436   revDesc=tmp->getNodalConnectivity();
6437   revDescIndx=tmp->getNodalConnectivityIndex();
6438   DataArrayInt *ret=0;
6439   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6440     {
6441       int tmp2;
6442       ret->getMaxValue(tmp2);
6443       ret->decrRef();
6444       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6445       throw INTERP_KERNEL::Exception(oss.str().c_str());
6446     }
6447   nM1LevMeshIds=ret;
6448   //
6449   revDesc->incrRef();
6450   revDescIndx->incrRef();
6451   ret1->incrRef();
6452   ret0->incrRef();
6453   meshnM1Old2New=ret0;
6454   return ret1;
6455 }
6456
6457 /*!
6458  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6459  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6460  * in "Old to New" mode.
6461  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6462  *          this array using decrRef() as it is no more needed.
6463  *  \throw If the nodal connectivity of cells is not defined.
6464  */
6465 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6466 {
6467   checkConnectivityFullyDefined();
6468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6469   renumberCells(ret->getConstPointer(),false);
6470   return ret.retn();
6471 }
6472
6473 /*!
6474  * This methods checks that cells are sorted by their types.
6475  * This method makes asumption (no check) that connectivity is correctly set before calling.
6476  */
6477 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6478 {
6479   checkFullyDefined();
6480   const int *conn=_nodal_connec->getConstPointer();
6481   const int *connI=_nodal_connec_index->getConstPointer();
6482   int nbOfCells=getNumberOfCells();
6483   std::set<INTERP_KERNEL::NormalizedCellType> types;
6484   for(const int *i=connI;i!=connI+nbOfCells;)
6485     {
6486       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6487       if(types.find(curType)!=types.end())
6488         return false;
6489       types.insert(curType);
6490       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6491     }
6492   return true;
6493 }
6494
6495 /*!
6496  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6497  * The geometric type order is specified by MED file.
6498  * 
6499  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6500  */
6501 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6502 {
6503   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6504 }
6505
6506 /*!
6507  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6508  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6509  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6510  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6511  */
6512 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6513 {
6514   checkFullyDefined();
6515   const int *conn=_nodal_connec->getConstPointer();
6516   const int *connI=_nodal_connec_index->getConstPointer();
6517   int nbOfCells=getNumberOfCells();
6518   if(nbOfCells==0)
6519     return true;
6520   int lastPos=-1;
6521   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6522   for(const int *i=connI;i!=connI+nbOfCells;)
6523     {
6524       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6525       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6526       if(isTypeExists!=orderEnd)
6527         {
6528           int pos=(int)std::distance(orderBg,isTypeExists);
6529           if(pos<=lastPos)
6530             return false;
6531           lastPos=pos;
6532           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6533         }
6534       else
6535         {
6536           if(sg.find(curType)==sg.end())
6537             {
6538               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6539               sg.insert(curType);
6540             }
6541           else
6542             return false;
6543         }
6544     }
6545   return true;
6546 }
6547
6548 /*!
6549  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6550  * 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
6551  * 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'.
6552  */
6553 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6554 {
6555   checkConnectivityFullyDefined();
6556   int nbOfCells=getNumberOfCells();
6557   const int *conn=_nodal_connec->getConstPointer();
6558   const int *connI=_nodal_connec_index->getConstPointer();
6559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6561   tmpa->alloc(nbOfCells,1);
6562   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6563   tmpb->fillWithZero();
6564   int *tmp=tmpa->getPointer();
6565   int *tmp2=tmpb->getPointer();
6566   for(const int *i=connI;i!=connI+nbOfCells;i++)
6567     {
6568       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6569       if(where!=orderEnd)
6570         {
6571           int pos=(int)std::distance(orderBg,where);
6572           tmp2[pos]++;
6573           tmp[std::distance(connI,i)]=pos;
6574         }
6575       else
6576         {
6577           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6578           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6579           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6580           throw INTERP_KERNEL::Exception(oss.str().c_str());
6581         }
6582     }
6583   nbPerType=tmpb.retn();
6584   return tmpa.retn();
6585 }
6586
6587 /*!
6588  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6589  *
6590  * \return a new object containing the old to new correspondance.
6591  *
6592  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6593  */
6594 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6595 {
6596   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6597 }
6598
6599 /*!
6600  * 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.
6601  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6602  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6603  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6604  */
6605 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6606 {
6607   DataArrayInt *nbPerType=0;
6608   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6609   nbPerType->decrRef();
6610   return tmpa->buildPermArrPerLevel();
6611 }
6612
6613 /*!
6614  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6615  * The number of cells remains unchanged after the call of this method.
6616  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6617  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6618  *
6619  * \return the array giving the correspondance old to new.
6620  */
6621 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6622 {
6623   checkFullyDefined();
6624   computeTypes();
6625   const int *conn=_nodal_connec->getConstPointer();
6626   const int *connI=_nodal_connec_index->getConstPointer();
6627   int nbOfCells=getNumberOfCells();
6628   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6629   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6630     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6631       {
6632         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6633         types.push_back(curType);
6634         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6635       }
6636   DataArrayInt *ret=DataArrayInt::New();
6637   ret->alloc(nbOfCells,1);
6638   int *retPtr=ret->getPointer();
6639   std::fill(retPtr,retPtr+nbOfCells,-1);
6640   int newCellId=0;
6641   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6642     {
6643       for(const int *i=connI;i!=connI+nbOfCells;i++)
6644         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6645           retPtr[std::distance(connI,i)]=newCellId++;
6646     }
6647   renumberCells(retPtr,false);
6648   return ret;
6649 }
6650
6651 /*!
6652  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6653  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6654  * This method makes asumption that connectivity is correctly set before calling.
6655  */
6656 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6657 {
6658   checkFullyDefined();
6659   const int *conn=_nodal_connec->getConstPointer();
6660   const int *connI=_nodal_connec_index->getConstPointer();
6661   int nbOfCells=getNumberOfCells();
6662   std::vector<MEDCouplingUMesh *> ret;
6663   for(const int *i=connI;i!=connI+nbOfCells;)
6664     {
6665       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6666       int beginCellId=(int)std::distance(connI,i);
6667       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6668       int endCellId=(int)std::distance(connI,i);
6669       int sz=endCellId-beginCellId;
6670       int *cells=new int[sz];
6671       for(int j=0;j<sz;j++)
6672         cells[j]=beginCellId+j;
6673       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6674       delete [] cells;
6675       ret.push_back(m);
6676     }
6677   return ret;
6678 }
6679
6680 /*!
6681  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6682  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6683  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6684  *
6685  * \return a newly allocated instance, that the caller must manage.
6686  * \throw If \a this contains more than one geometric type.
6687  * \throw If the nodal connectivity of \a this is not fully defined.
6688  * \throw If the internal data is not coherent.
6689  */
6690 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6691 {
6692   checkConnectivityFullyDefined();
6693     if(_types.size()!=1)
6694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6695   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6696   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6697   ret->setCoords(getCoords());
6698   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6699   if(retC)
6700     retC->setNodalConnectivity(convertNodalConnectivityToStaticGeoTypeMesh());
6701   else
6702     {
6703       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6704       if(!retD)
6705         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6706       DataArrayInt *c=0,*ci=0;
6707       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6708       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6709       retD->setNodalConnectivity(cs,cis);
6710     }
6711   return ret.retn();
6712 }
6713
6714 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6715 {
6716   checkConnectivityFullyDefined();
6717     if(_types.size()!=1)
6718     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6719   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6720   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6721   if(cm.isDynamic())
6722     {
6723       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6724       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6725       throw INTERP_KERNEL::Exception(oss.str().c_str());
6726     }
6727   int nbCells=getNumberOfCells();
6728   int typi=(int)typ;
6729   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6731   int *outPtr=connOut->getPointer();
6732   const int *conn=_nodal_connec->begin();
6733   const int *connI=_nodal_connec_index->begin();
6734   nbNodesPerCell++;
6735   for(int i=0;i<nbCells;i++,connI++)
6736     {
6737       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6738         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6739       else
6740         {
6741           std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6742           throw INTERP_KERNEL::Exception(oss.str().c_str());
6743         }
6744     }
6745   return connOut.retn();
6746 }
6747
6748 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6749 {
6750   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6751   checkConnectivityFullyDefined();
6752   if(_types.size()!=1)
6753     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6754   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6755   if(lgth<nbCells)
6756     throw INTERP_KERNEL::Exception(msg0);
6757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6758   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6759   int *cp(c->getPointer()),*cip(ci->getPointer());
6760   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6761   for(int i=0;i<nbCells;i++,cip++,incip++)
6762     {
6763       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6764       int delta(stop-strt);
6765       if(delta>=1)
6766         {
6767           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6768             cp=std::copy(incp+strt,incp+stop,cp);
6769           else
6770             throw INTERP_KERNEL::Exception(msg0);
6771         }
6772       else
6773         throw INTERP_KERNEL::Exception(msg0);
6774       cip[1]=cip[0]+delta;
6775     }
6776   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6777 }
6778
6779 /*!
6780  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6781  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6782  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6783  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6784  * are not used here to avoid the build of big permutation array.
6785  *
6786  * \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
6787  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6788  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6789  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6790  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6791  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6792  * \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
6793  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6794  */
6795 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6796                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6797                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6798 {
6799   std::vector<const MEDCouplingUMesh *> ms2;
6800   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6801     if(*it)
6802       {
6803         (*it)->checkConnectivityFullyDefined();
6804         ms2.push_back(*it);
6805       }
6806   if(ms2.empty())
6807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6808   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6809   int meshDim=ms2[0]->getMeshDimension();
6810   std::vector<const MEDCouplingUMesh *> m1ssm;
6811   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6812   //
6813   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6814   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6815   int fake=0,rk=0;
6816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6817   ret1->alloc(0,1); ret2->alloc(0,1);
6818   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6819     {
6820       if(meshDim!=(*it)->getMeshDimension())
6821         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6822       if(refCoo!=(*it)->getCoords())
6823         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6824       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6825       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6826       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6827       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6828         {
6829           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6830           m1ssmSingleAuto.push_back(singleCell);
6831           m1ssmSingle.push_back(singleCell);
6832           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6833         }
6834     }
6835   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6837   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6838   for(std::size_t i=0;i<m1ssm.size();i++)
6839     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6840   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6841   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6842   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6843   return ret0.retn();
6844 }
6845
6846 /*!
6847  * This method returns a newly created DataArrayInt instance.
6848  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6849  */
6850 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6851 {
6852   checkFullyDefined();
6853   const int *conn=_nodal_connec->getConstPointer();
6854   const int *connIndex=_nodal_connec_index->getConstPointer();
6855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6856   for(const int *w=begin;w!=end;w++)
6857     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6858       ret->pushBackSilent(*w);
6859   return ret.retn();
6860 }
6861
6862 /*!
6863  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6864  * are in [0:getNumberOfCells())
6865  */
6866 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6867 {
6868   checkFullyDefined();
6869   const int *conn=_nodal_connec->getConstPointer();
6870   const int *connI=_nodal_connec_index->getConstPointer();
6871   int nbOfCells=getNumberOfCells();
6872   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6873   int *tmp=new int[nbOfCells];
6874   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6875     {
6876       int j=0;
6877       for(const int *i=connI;i!=connI+nbOfCells;i++)
6878         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6879           tmp[std::distance(connI,i)]=j++;
6880     }
6881   DataArrayInt *ret=DataArrayInt::New();
6882   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6883   ret->copyStringInfoFrom(*da);
6884   int *retPtr=ret->getPointer();
6885   const int *daPtr=da->getConstPointer();
6886   int nbOfElems=da->getNbOfElems();
6887   for(int k=0;k<nbOfElems;k++)
6888     retPtr[k]=tmp[daPtr[k]];
6889   delete [] tmp;
6890   return ret;
6891 }
6892
6893 /*!
6894  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6895  * This method \b works \b for mesh sorted by type.
6896  * cells whose ids is in 'idsPerGeoType' array.
6897  * This method conserves coords and name of mesh.
6898  */
6899 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6900 {
6901   std::vector<int> code=getDistributionOfTypes();
6902   std::size_t nOfTypesInThis=code.size()/3;
6903   int sz=0,szOfType=0;
6904   for(std::size_t i=0;i<nOfTypesInThis;i++)
6905     {
6906       if(code[3*i]!=type)
6907         sz+=code[3*i+1];
6908       else
6909         szOfType=code[3*i+1];
6910     }
6911   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6912     if(*work<0 || *work>=szOfType)
6913       {
6914         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6915         oss << ". It should be in [0," << szOfType << ") !";
6916         throw INTERP_KERNEL::Exception(oss.str().c_str());
6917       }
6918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6919   int *idsPtr=idsTokeep->getPointer();
6920   int offset=0;
6921   for(std::size_t i=0;i<nOfTypesInThis;i++)
6922     {
6923       if(code[3*i]!=type)
6924         for(int j=0;j<code[3*i+1];j++)
6925           *idsPtr++=offset+j;
6926       else
6927         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6928       offset+=code[3*i+1];
6929     }
6930   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6931   ret->copyTinyInfoFrom(this);
6932   return ret.retn();
6933 }
6934
6935 /*!
6936  * This method returns a vector of size 'this->getNumberOfCells()'.
6937  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6938  */
6939 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6940 {
6941   int ncell=getNumberOfCells();
6942   std::vector<bool> ret(ncell);
6943   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6944   const int *c=getNodalConnectivity()->getConstPointer();
6945   for(int i=0;i<ncell;i++)
6946     {
6947       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6948       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6949       ret[i]=cm.isQuadratic();
6950     }
6951   return ret;
6952 }
6953
6954 /*!
6955  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6956  */
6957 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6958 {
6959   if(other->getType()!=UNSTRUCTURED)
6960     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6961   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6962   return MergeUMeshes(this,otherC);
6963 }
6964
6965 /*!
6966  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6967  * computed by averaging coordinates of cell nodes, so this method is not a right
6968  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6969  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6970  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6971  *          components. The caller is to delete this array using decrRef() as it is
6972  *          no more needed.
6973  *  \throw If the coordinates array is not set.
6974  *  \throw If the nodal connectivity of cells is not defined.
6975  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6976  */
6977 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6978 {
6979   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6980   int spaceDim=getSpaceDimension();
6981   int nbOfCells=getNumberOfCells();
6982   ret->alloc(nbOfCells,spaceDim);
6983   ret->copyStringInfoFrom(*getCoords());
6984   double *ptToFill=ret->getPointer();
6985   const int *nodal=_nodal_connec->getConstPointer();
6986   const int *nodalI=_nodal_connec_index->getConstPointer();
6987   const double *coor=_coords->getConstPointer();
6988   for(int i=0;i<nbOfCells;i++)
6989     {
6990       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6991       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6992       ptToFill+=spaceDim;
6993     }
6994   return ret.retn();
6995 }
6996
6997 /*!
6998  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6999  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7000  * 
7001  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7002  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7003  * 
7004  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7005  * \throw If \a this is not fully defined (coordinates and connectivity)
7006  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7007  */
7008 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7009 {
7010   checkFullyDefined();
7011   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7012   int spaceDim=getSpaceDimension();
7013   int nbOfCells=getNumberOfCells();
7014   int nbOfNodes=getNumberOfNodes();
7015   ret->alloc(nbOfCells,spaceDim);
7016   double *ptToFill=ret->getPointer();
7017   const int *nodal=_nodal_connec->getConstPointer();
7018   const int *nodalI=_nodal_connec_index->getConstPointer();
7019   const double *coor=_coords->getConstPointer();
7020   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7021     {
7022       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7023       std::fill(ptToFill,ptToFill+spaceDim,0.);
7024       if(type!=INTERP_KERNEL::NORM_POLYHED)
7025         {
7026           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7027             {
7028               if(*conn>=0 && *conn<nbOfNodes)
7029                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7030               else
7031                 {
7032                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7033                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7034                 }
7035             }
7036           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7037           if(nbOfNodesInCell>0)
7038             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7039           else
7040             {
7041               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7042               throw INTERP_KERNEL::Exception(oss.str().c_str());
7043             }
7044         }
7045       else
7046         {
7047           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7048           s.erase(-1);
7049           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7050             {
7051               if(*it>=0 && *it<nbOfNodes)
7052                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7053               else
7054                 {
7055                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7056                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7057                 }
7058             }
7059           if(!s.empty())
7060             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7061           else
7062             {
7063               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7064               throw INTERP_KERNEL::Exception(oss.str().c_str());
7065             }
7066         }
7067     }
7068   return ret.retn();
7069 }
7070
7071 /*!
7072  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7073  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7074  * are specified via an array of cell ids. 
7075  *  \warning Validity of the specified cell ids is not checked! 
7076  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7077  *  \param [in] begin - an array of cell ids of interest.
7078  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7079  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7080  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7081  *          caller is to delete this array using decrRef() as it is no more needed. 
7082  *  \throw If the coordinates array is not set.
7083  *  \throw If the nodal connectivity of cells is not defined.
7084  *
7085  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7086  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7087  */
7088 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7089 {
7090   DataArrayDouble *ret=DataArrayDouble::New();
7091   int spaceDim=getSpaceDimension();
7092   int nbOfTuple=(int)std::distance(begin,end);
7093   ret->alloc(nbOfTuple,spaceDim);
7094   double *ptToFill=ret->getPointer();
7095   double *tmp=new double[spaceDim];
7096   const int *nodal=_nodal_connec->getConstPointer();
7097   const int *nodalI=_nodal_connec_index->getConstPointer();
7098   const double *coor=_coords->getConstPointer();
7099   for(const int *w=begin;w!=end;w++)
7100     {
7101       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7102       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7103       ptToFill+=spaceDim;
7104     }
7105   delete [] tmp;
7106   return ret;
7107 }
7108
7109 /*!
7110  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7111  * 
7112  */
7113 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7114 {
7115   if(!da)
7116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7117   da->checkAllocated();
7118   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7119   ret->setCoords(da);
7120   int nbOfTuples=da->getNumberOfTuples();
7121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7123   c->alloc(2*nbOfTuples,1);
7124   cI->alloc(nbOfTuples+1,1);
7125   int *cp=c->getPointer();
7126   int *cip=cI->getPointer();
7127   *cip++=0;
7128   for(int i=0;i<nbOfTuples;i++)
7129     {
7130       *cp++=INTERP_KERNEL::NORM_POINT1;
7131       *cp++=i;
7132       *cip++=2*(i+1);
7133     }
7134   ret->setConnectivity(c,cI,true);
7135   return ret.retn();
7136 }
7137 /*!
7138  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7139  * Cells and nodes of
7140  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7141  *  \param [in] mesh1 - the first mesh.
7142  *  \param [in] mesh2 - the second mesh.
7143  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7144  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7145  *          is no more needed.
7146  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7147  *  \throw If the coordinates array is not set in none of the meshes.
7148  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7149  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7150  */
7151 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7152 {
7153   std::vector<const MEDCouplingUMesh *> tmp(2);
7154   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7155   return MergeUMeshes(tmp);
7156 }
7157
7158 /*!
7159  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7160  * Cells and nodes of
7161  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7162  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7163  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7164  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7165  *          is no more needed.
7166  *  \throw If \a a.size() == 0.
7167  *  \throw If \a a[ *i* ] == NULL.
7168  *  \throw If the coordinates array is not set in none of the meshes.
7169  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7170  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7171 */
7172 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7173 {
7174   std::size_t sz=a.size();
7175   if(sz==0)
7176     return MergeUMeshesLL(a);
7177   for(std::size_t ii=0;ii<sz;ii++)
7178     if(!a[ii])
7179       {
7180         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7181         throw INTERP_KERNEL::Exception(oss.str().c_str());
7182       }
7183   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7184   std::vector< const MEDCouplingUMesh * > aa(sz);
7185   int spaceDim=-3;
7186   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7187     {
7188       const MEDCouplingUMesh *cur=a[i];
7189       const DataArrayDouble *coo=cur->getCoords();
7190       if(coo)
7191         spaceDim=coo->getNumberOfComponents();
7192     }
7193   if(spaceDim==-3)
7194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7195   for(std::size_t i=0;i<sz;i++)
7196     {
7197       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7198       aa[i]=bb[i];
7199     }
7200   return MergeUMeshesLL(aa);
7201 }
7202
7203 /// @cond INTERNAL
7204
7205 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7206 {
7207   if(a.empty())
7208     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7209   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7210   int meshDim=(*it)->getMeshDimension();
7211   int nbOfCells=(*it)->getNumberOfCells();
7212   int meshLgth=(*it++)->getMeshLength();
7213   for(;it!=a.end();it++)
7214     {
7215       if(meshDim!=(*it)->getMeshDimension())
7216         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7217       nbOfCells+=(*it)->getNumberOfCells();
7218       meshLgth+=(*it)->getMeshLength();
7219     }
7220   std::vector<const MEDCouplingPointSet *> aps(a.size());
7221   std::copy(a.begin(),a.end(),aps.begin());
7222   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7223   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7224   ret->setCoords(pts);
7225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7226   c->alloc(meshLgth,1);
7227   int *cPtr=c->getPointer();
7228   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7229   cI->alloc(nbOfCells+1,1);
7230   int *cIPtr=cI->getPointer();
7231   *cIPtr++=0;
7232   int offset=0;
7233   int offset2=0;
7234   for(it=a.begin();it!=a.end();it++)
7235     {
7236       int curNbOfCell=(*it)->getNumberOfCells();
7237       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7238       const int *curC=(*it)->_nodal_connec->getConstPointer();
7239       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7240       for(int j=0;j<curNbOfCell;j++)
7241         {
7242           const int *src=curC+curCI[j];
7243           *cPtr++=*src++;
7244           for(;src!=curC+curCI[j+1];src++,cPtr++)
7245             {
7246               if(*src!=-1)
7247                 *cPtr=*src+offset2;
7248               else
7249                 *cPtr=-1;
7250             }
7251         }
7252       offset+=curCI[curNbOfCell];
7253       offset2+=(*it)->getNumberOfNodes();
7254     }
7255   //
7256   ret->setConnectivity(c,cI,true);
7257   return ret.retn();
7258 }
7259
7260 /// @endcond
7261
7262 /*!
7263  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7264  * dimension and sharing the node coordinates array.
7265  * All cells of the first mesh precede all cells of the second mesh
7266  * within the result mesh. 
7267  *  \param [in] mesh1 - the first mesh.
7268  *  \param [in] mesh2 - the second mesh.
7269  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7270  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7271  *          is no more needed.
7272  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7273  *  \throw If the meshes do not share the node coordinates array.
7274  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7275  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7276  */
7277 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7278 {
7279   std::vector<const MEDCouplingUMesh *> tmp(2);
7280   tmp[0]=mesh1; tmp[1]=mesh2;
7281   return MergeUMeshesOnSameCoords(tmp);
7282 }
7283
7284 /*!
7285  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7286  * dimension and sharing the node coordinates array.
7287  * All cells of the *i*-th mesh precede all cells of the
7288  * (*i*+1)-th mesh within the result mesh.
7289  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7290  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7291  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7292  *          is no more needed.
7293  *  \throw If \a a.size() == 0.
7294  *  \throw If \a a[ *i* ] == NULL.
7295  *  \throw If the meshes do not share the node coordinates array.
7296  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7297  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7298  */
7299 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7300 {
7301   if(meshes.empty())
7302     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7303   for(std::size_t ii=0;ii<meshes.size();ii++)
7304     if(!meshes[ii])
7305       {
7306         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7307         throw INTERP_KERNEL::Exception(oss.str().c_str());
7308       }
7309   const DataArrayDouble *coords=meshes.front()->getCoords();
7310   int meshDim=meshes.front()->getMeshDimension();
7311   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7312   int meshLgth=0;
7313   int meshIndexLgth=0;
7314   for(;iter!=meshes.end();iter++)
7315     {
7316       if(coords!=(*iter)->getCoords())
7317         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7318       if(meshDim!=(*iter)->getMeshDimension())
7319         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7320       meshLgth+=(*iter)->getMeshLength();
7321       meshIndexLgth+=(*iter)->getNumberOfCells();
7322     }
7323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7324   nodal->alloc(meshLgth,1);
7325   int *nodalPtr=nodal->getPointer();
7326   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7327   nodalIndex->alloc(meshIndexLgth+1,1);
7328   int *nodalIndexPtr=nodalIndex->getPointer();
7329   int offset=0;
7330   for(iter=meshes.begin();iter!=meshes.end();iter++)
7331     {
7332       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7333       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7334       int nbOfCells=(*iter)->getNumberOfCells();
7335       int meshLgth2=(*iter)->getMeshLength();
7336       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7337       if(iter!=meshes.begin())
7338         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7339       else
7340         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7341       offset+=meshLgth2;
7342     }
7343   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7344   ret->setName("merge");
7345   ret->setMeshDimension(meshDim);
7346   ret->setConnectivity(nodal,nodalIndex,true);
7347   ret->setCoords(coords);
7348   return ret;
7349 }
7350
7351 /*!
7352  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7353  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7354  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7355  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7356  * New" mode are returned for each input mesh.
7357  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7358  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7359  *          valid values [0,1,2], see zipConnectivityTraducer().
7360  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7361  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7362  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7363  *          no more needed.
7364  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7365  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7366  *          is no more needed.
7367  *  \throw If \a meshes.size() == 0.
7368  *  \throw If \a meshes[ *i* ] == NULL.
7369  *  \throw If the meshes do not share the node coordinates array.
7370  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7371  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7372  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7373  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7374  */
7375 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7376 {
7377   //All checks are delegated to MergeUMeshesOnSameCoords
7378   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7380   corr.resize(meshes.size());
7381   std::size_t nbOfMeshes=meshes.size();
7382   int offset=0;
7383   const int *o2nPtr=o2n->getConstPointer();
7384   for(std::size_t i=0;i<nbOfMeshes;i++)
7385     {
7386       DataArrayInt *tmp=DataArrayInt::New();
7387       int curNbOfCells=meshes[i]->getNumberOfCells();
7388       tmp->alloc(curNbOfCells,1);
7389       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7390       offset+=curNbOfCells;
7391       tmp->setName(meshes[i]->getName());
7392       corr[i]=tmp;
7393     }
7394   return ret.retn();
7395 }
7396
7397 /*!
7398  * Makes all given meshes share the nodal connectivity array. The common connectivity
7399  * array is created by concatenating the connectivity arrays of all given meshes. All
7400  * the given meshes must be of the same space dimension but dimension of cells **can
7401  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7402  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7403  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7404  *  \param [in,out] meshes - a vector of meshes to update.
7405  *  \throw If any of \a meshes is NULL.
7406  *  \throw If the coordinates array is not set in any of \a meshes.
7407  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7408  *  \throw If \a meshes are of different space dimension.
7409  */
7410 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7411 {
7412   std::size_t sz=meshes.size();
7413   if(sz==0 || sz==1)
7414     return;
7415   std::vector< const DataArrayDouble * > coords(meshes.size());
7416   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7417   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7418     {
7419       if((*it))
7420         {
7421           (*it)->checkConnectivityFullyDefined();
7422           const DataArrayDouble *coo=(*it)->getCoords();
7423           if(coo)
7424             *it2=coo;
7425           else
7426             {
7427               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7428               oss << " has no coordinate array defined !";
7429               throw INTERP_KERNEL::Exception(oss.str().c_str());
7430             }
7431         }
7432       else
7433         {
7434           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7435           oss << " is null !";
7436           throw INTERP_KERNEL::Exception(oss.str().c_str());
7437         }
7438     }
7439   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7440   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7441   int offset=(*it)->getNumberOfNodes();
7442   (*it++)->setCoords(res);
7443   for(;it!=meshes.end();it++)
7444     {
7445       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7446       (*it)->setCoords(res);
7447       (*it)->shiftNodeNumbersInConn(offset);
7448       offset+=oldNumberOfNodes;
7449     }
7450 }
7451
7452 /*!
7453  * Merges nodes coincident with a given precision within all given meshes that share
7454  * the nodal connectivity array. The given meshes **can be of different** mesh
7455  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7456  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7457  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7458  *  \param [in,out] meshes - a vector of meshes to update.
7459  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7460  *  \throw If any of \a meshes is NULL.
7461  *  \throw If the \a meshes do not share the same node coordinates array.
7462  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7463  */
7464 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7465 {
7466   if(meshes.empty())
7467     return ;
7468   std::set<const DataArrayDouble *> s;
7469   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7470     {
7471       if(*it)
7472         s.insert((*it)->getCoords());
7473       else
7474         {
7475           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 !";
7476           throw INTERP_KERNEL::Exception(oss.str().c_str());
7477         }
7478     }
7479   if(s.size()!=1)
7480     {
7481       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 !";
7482       throw INTERP_KERNEL::Exception(oss.str().c_str());
7483     }
7484   const DataArrayDouble *coo=*(s.begin());
7485   if(!coo)
7486     return;
7487   //
7488   DataArrayInt *comm,*commI;
7489   coo->findCommonTuples(eps,-1,comm,commI);
7490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7491   int oldNbOfNodes=coo->getNumberOfTuples();
7492   int newNbOfNodes;
7493   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7494   if(oldNbOfNodes==newNbOfNodes)
7495     return ;
7496   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7497   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7498     {
7499       (*it)->renumberNodesInConn(o2n->getConstPointer());
7500       (*it)->setCoords(newCoords);
7501     } 
7502 }
7503
7504 /*!
7505  * 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.
7506  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7507  * \param isQuad specifies the policy of connectivity.
7508  * @ret in/out parameter in which the result will be append
7509  */
7510 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7511 {
7512   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7513   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7514   ret.push_back(cm.getExtrudedType());
7515   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7516   switch(flatType)
7517     {
7518     case INTERP_KERNEL::NORM_POINT1:
7519       {
7520         ret.push_back(connBg[1]);
7521         ret.push_back(connBg[1]+nbOfNodesPerLev);
7522         break;
7523       }
7524     case INTERP_KERNEL::NORM_SEG2:
7525       {
7526         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7527         ret.insert(ret.end(),conn,conn+4);
7528         break;
7529       }
7530     case INTERP_KERNEL::NORM_SEG3:
7531       {
7532         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7533         ret.insert(ret.end(),conn,conn+8);
7534         break;
7535       }
7536     case INTERP_KERNEL::NORM_QUAD4:
7537       {
7538         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7539         ret.insert(ret.end(),conn,conn+8);
7540         break;
7541       }
7542     case INTERP_KERNEL::NORM_TRI3:
7543       {
7544         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7545         ret.insert(ret.end(),conn,conn+6);
7546         break;
7547       }
7548     case INTERP_KERNEL::NORM_TRI6:
7549       {
7550         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,
7551                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7552         ret.insert(ret.end(),conn,conn+15);
7553         break;
7554       }
7555     case INTERP_KERNEL::NORM_QUAD8:
7556       {
7557         int conn[20]={
7558           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7559           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7560           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7561         };
7562         ret.insert(ret.end(),conn,conn+20);
7563         break;
7564       }
7565     case INTERP_KERNEL::NORM_POLYGON:
7566       {
7567         std::back_insert_iterator< std::vector<int> > ii(ret);
7568         std::copy(connBg+1,connEnd,ii);
7569         *ii++=-1;
7570         std::reverse_iterator<const int *> rConnBg(connEnd);
7571         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7572         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7573         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7574         for(std::size_t i=0;i<nbOfRadFaces;i++)
7575           {
7576             *ii++=-1;
7577             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7578             std::copy(conn,conn+4,ii);
7579           }
7580         break;
7581       }
7582     default:
7583       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7584     }
7585 }
7586
7587 /*!
7588  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7589  */
7590 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7591 {
7592   double v[3]={0.,0.,0.};
7593   std::size_t sz=std::distance(begin,end);
7594   if(isQuadratic)
7595     sz/=2;
7596   for(std::size_t i=0;i<sz;i++)
7597     {
7598       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];
7599       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7600       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7601     }
7602   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7603 }
7604
7605 /*!
7606  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7607  */
7608 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7609 {
7610   std::vector<std::pair<int,int> > edges;
7611   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7612   const int *bgFace=begin;
7613   for(std::size_t i=0;i<nbOfFaces;i++)
7614     {
7615       const int *endFace=std::find(bgFace+1,end,-1);
7616       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7617       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7618         {
7619           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7620           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7621             return false;
7622           edges.push_back(p1);
7623         }
7624       bgFace=endFace+1;
7625     }
7626   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7627 }
7628
7629 /*!
7630  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7631  */
7632 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7633 {
7634   double vec0[3],vec1[3];
7635   std::size_t sz=std::distance(begin,end);
7636   if(sz%2!=0)
7637     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7638   int nbOfNodes=(int)sz/2;
7639   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7640   const double *pt0=coords+3*begin[0];
7641   const double *pt1=coords+3*begin[nbOfNodes];
7642   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7643   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7644 }
7645
7646 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7647 {
7648   std::size_t sz=std::distance(begin,end);
7649   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7650   std::size_t nbOfNodes(sz/2);
7651   std::copy(begin,end,(int *)tmp);
7652   for(std::size_t j=1;j<nbOfNodes;j++)
7653     {
7654       begin[j]=tmp[nbOfNodes-j];
7655       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7656     }
7657 }
7658
7659 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7660 {
7661   std::size_t sz=std::distance(begin,end);
7662   if(sz!=4)
7663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7664   double vec0[3],vec1[3];
7665   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7666   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]; 
7667   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;
7668 }
7669
7670 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7671 {
7672   std::size_t sz=std::distance(begin,end);
7673   if(sz!=5)
7674     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7675   double vec0[3];
7676   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7677   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7678   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7679 }
7680
7681 /*!
7682  * 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 ) 
7683  * 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
7684  * a 2D space.
7685  *
7686  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7687  * \param [in] coords the coordinates with nb of components exactly equal to 3
7688  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7689  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7690  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7691  */
7692 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7693 {
7694   int nbFaces=std::count(begin+1,end,-1)+1;
7695   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7696   double *vPtr=v->getPointer();
7697   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7698   double *pPtr=p->getPointer();
7699   const int *stFaceConn=begin+1;
7700   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7701     {
7702       const int *endFaceConn=std::find(stFaceConn,end,-1);
7703       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7704       stFaceConn=endFaceConn+1;
7705     }
7706   pPtr=p->getPointer(); vPtr=v->getPointer();
7707   DataArrayInt *comm1=0,*commI1=0;
7708   v->findCommonTuples(eps,-1,comm1,commI1);
7709   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7710   const int *comm1Ptr=comm1->getConstPointer();
7711   const int *commI1Ptr=commI1->getConstPointer();
7712   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7713   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7714   //
7715   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7716   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7717   mm->finishInsertingCells();
7718   //
7719   for(int i=0;i<nbOfGrps1;i++)
7720     {
7721       int vecId=comm1Ptr[commI1Ptr[i]];
7722       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7723       DataArrayInt *comm2=0,*commI2=0;
7724       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7725       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7726       const int *comm2Ptr=comm2->getConstPointer();
7727       const int *commI2Ptr=commI2->getConstPointer();
7728       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7729       for(int j=0;j<nbOfGrps2;j++)
7730         {
7731           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7732             {
7733               res->insertAtTheEnd(begin,end);
7734               res->pushBackSilent(-1);
7735             }
7736           else
7737             {
7738               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7739               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7740               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7741               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7742               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7743               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7744               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7745               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7746               const int *idsNodePtr=idsNode->getConstPointer();
7747               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];
7748               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7749               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7750               if(std::abs(norm)>eps)
7751                 {
7752                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7753                   mm3->rotate(center,vec,angle);
7754                 }
7755               mm3->changeSpaceDimension(2);
7756               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7757               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7758               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7759               int nbOfCells=mm4->getNumberOfCells();
7760               for(int k=0;k<nbOfCells;k++)
7761                 {
7762                   int l=0;
7763                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7764                     res->pushBackSilent(idsNodePtr[*work]);
7765                   res->pushBackSilent(-1);
7766                 }
7767             }
7768         }
7769     }
7770   res->popBackSilent();
7771 }
7772
7773 /*!
7774  * 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
7775  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7776  * 
7777  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7778  * \param [in] coords coordinates expected to have 3 components.
7779  * \param [in] begin start of the nodal connectivity of the face.
7780  * \param [in] end end of the nodal connectivity (excluded) of the face.
7781  * \param [out] v the normalized vector of size 3
7782  * \param [out] p the pos of plane
7783  */
7784 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7785 {
7786   std::size_t nbPoints=std::distance(begin,end);
7787   if(nbPoints<3)
7788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7789   double vec[3]={0.,0.,0.};
7790   std::size_t j=0;
7791   bool refFound=false;
7792   for(;j<nbPoints-1 && !refFound;j++)
7793     {
7794       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7795       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7796       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7797       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7798       if(norm>eps)
7799         {
7800           refFound=true;
7801           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7802         }
7803     }
7804   for(std::size_t i=j;i<nbPoints-1;i++)
7805     {
7806       double curVec[3];
7807       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7808       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7809       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7810       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7811       if(norm<eps)
7812         continue;
7813       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7814       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];
7815       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7816       if(norm>eps)
7817         {
7818           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7819           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7820           return ;
7821         }
7822     }
7823   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7824 }
7825
7826 /*!
7827  * This method tries to obtain a well oriented polyhedron.
7828  * If the algorithm fails, an exception will be thrown.
7829  */
7830 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7831 {
7832   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7833   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7834   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7835   isPerm[0]=true;
7836   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7837   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7838   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7839   //
7840   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7841     {
7842       bgFace=begin;
7843       std::size_t smthChanged=0;
7844       for(std::size_t i=0;i<nbOfFaces;i++)
7845         {
7846           endFace=std::find(bgFace+1,end,-1);
7847           nbOfEdgesInFace=std::distance(bgFace,endFace);
7848           if(!isPerm[i])
7849             {
7850               bool b;
7851               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7852                 {
7853                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7854                   std::pair<int,int> p2(p1.second,p1.first);
7855                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7856                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7857                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7858                 }
7859               if(isPerm[i])
7860                 { 
7861                   if(!b)
7862                     std::reverse(bgFace+1,endFace);
7863                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7864                     {
7865                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7866                       std::pair<int,int> p2(p1.second,p1.first);
7867                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7868                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7869                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7870                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7871                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7872                       if(it!=edgesOK.end())
7873                         {
7874                           edgesOK.erase(it);
7875                           edgesFinished.push_back(p1);
7876                         }
7877                       else
7878                         edgesOK.push_back(p1);
7879                     }
7880                 }
7881             }
7882           bgFace=endFace+1;
7883         }
7884       if(smthChanged==0)
7885         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7886     }
7887   if(!edgesOK.empty())
7888     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7889   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7890     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7891       bgFace=begin;
7892       for(std::size_t i=0;i<nbOfFaces;i++)
7893         {
7894           endFace=std::find(bgFace+1,end,-1);
7895           std::reverse(bgFace+1,endFace);
7896           bgFace=endFace+1;
7897         }
7898     }
7899 }
7900
7901 /*!
7902  * This method makes the assumption spacedimension == meshdimension == 2.
7903  * This method works only for linear cells.
7904  * 
7905  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7906  */
7907 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7908 {
7909   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7911   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7913   int nbOfNodesExpected=m->getNumberOfNodes();
7914   if(m->getNumberOfCells()!=nbOfNodesExpected)
7915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7916   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7917   const int *n2oPtr=n2o->getConstPointer();
7918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7919   m->getReverseNodalConnectivity(revNodal,revNodalI);
7920   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7921   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7922   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7924   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7925   if(nbOfNodesExpected<1)
7926     return ret.retn();
7927   int prevCell=0;
7928   int prevNode=nodalPtr[nodalIPtr[0]+1];
7929   *work++=n2oPtr[prevNode];
7930   for(int i=1;i<nbOfNodesExpected;i++)
7931     {
7932       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7933         {
7934           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7935           conn.erase(prevNode);
7936           if(conn.size()==1)
7937             {
7938               int curNode=*(conn.begin());
7939               *work++=n2oPtr[curNode];
7940               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7941               shar.erase(prevCell);
7942               if(shar.size()==1)
7943                 {
7944                   prevCell=*(shar.begin());
7945                   prevNode=curNode;
7946                 }
7947               else
7948                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7949             }
7950           else
7951             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7952         }
7953       else
7954         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7955     }
7956   return ret.retn();
7957 }
7958
7959 /*!
7960  * This method makes the assumption spacedimension == meshdimension == 3.
7961  * This method works only for linear cells.
7962  * 
7963  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7964  */
7965 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7966 {
7967   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7969   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7970   const int *conn=m->getNodalConnectivity()->getConstPointer();
7971   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7972   int nbOfCells=m->getNumberOfCells();
7973   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7974   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7975   if(nbOfCells<1)
7976     return ret.retn();
7977   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7978   for(int i=1;i<nbOfCells;i++)
7979     {
7980       *work++=-1;
7981       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7982     }
7983   return ret.retn();
7984 }
7985
7986 /*!
7987  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7988  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7989  */
7990 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7991 {
7992   double *w=zipFrmt;
7993   if(spaceDim==3)
7994     for(int i=0;i<nbOfNodesInCell;i++)
7995       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7996   else if(spaceDim==2)
7997     {
7998       for(int i=0;i<nbOfNodesInCell;i++)
7999         {
8000           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8001           *w++=0.;
8002         }
8003     }
8004   else
8005     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8006 }
8007
8008 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8009 {
8010   int nbOfCells=getNumberOfCells();
8011   if(nbOfCells<=0)
8012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8013   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};
8014   ofs << "  <" << getVTKDataSetType() << ">\n";
8015   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8016   ofs << "      <PointData>\n" << pointData << std::endl;
8017   ofs << "      </PointData>\n";
8018   ofs << "      <CellData>\n" << cellData << std::endl;
8019   ofs << "      </CellData>\n";
8020   ofs << "      <Points>\n";
8021   if(getSpaceDimension()==3)
8022     _coords->writeVTK(ofs,8,"Points");
8023   else
8024     {
8025       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8026       coo->writeVTK(ofs,8,"Points");
8027     }
8028   ofs << "      </Points>\n";
8029   ofs << "      <Cells>\n";
8030   const int *cPtr=_nodal_connec->getConstPointer();
8031   const int *cIPtr=_nodal_connec_index->getConstPointer();
8032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8036   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8037   int szFaceOffsets=0,szConn=0;
8038   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8039     {
8040       *w2=cPtr[cIPtr[i]];
8041       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8042         {
8043           *w1=-1;
8044           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8045           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8046         }
8047       else
8048         {
8049           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8050           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8051           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8052           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8053           w4=std::copy(c.begin(),c.end(),w4);
8054         }
8055     }
8056   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8057   types->writeVTK(ofs,8,"UInt8","types");
8058   offsets->writeVTK(ofs,8,"Int32","offsets");
8059   if(szFaceOffsets!=0)
8060     {//presence of Polyhedra
8061       connectivity->reAlloc(szConn);
8062       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8063       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8064       w1=faces->getPointer();
8065       for(int i=0;i<nbOfCells;i++)
8066         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8067           {
8068             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8069             *w1++=nbFaces;
8070             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8071             for(int j=0;j<nbFaces;j++)
8072               {
8073                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8074                 *w1++=(int)std::distance(w6,w5);
8075                 w1=std::copy(w6,w5,w1);
8076                 w6=w5+1;
8077               }
8078           }
8079       faces->writeVTK(ofs,8,"Int32","faces");
8080     }
8081   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8082   ofs << "      </Cells>\n";
8083   ofs << "    </Piece>\n";
8084   ofs << "  </" << getVTKDataSetType() << ">\n";
8085 }
8086
8087 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8088 {
8089   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8090   if(_mesh_dim==-2)
8091     { stream << " Not set !"; return ; }
8092   stream << " Mesh dimension : " << _mesh_dim << ".";
8093   if(_mesh_dim==-1)
8094     return ;
8095   if(!_coords)
8096     { stream << " No coordinates set !"; return ; }
8097   if(!_coords->isAllocated())
8098     { stream << " Coordinates set but not allocated !"; return ; }
8099   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8100   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8101   if(!_nodal_connec_index)
8102     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8103   if(!_nodal_connec_index->isAllocated())
8104     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8105   int lgth=_nodal_connec_index->getNumberOfTuples();
8106   int cpt=_nodal_connec_index->getNumberOfComponents();
8107   if(cpt!=1 || lgth<1)
8108     return ;
8109   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8110 }
8111
8112 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8113 {
8114   return std::string("UnstructuredGrid");
8115 }
8116
8117 /*!
8118  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8119  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8120  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8121  * meshes.
8122  *  \param [in] m1 - the first input mesh which is a partitioned object.
8123  *  \param [in] m2 - the second input mesh which is a partition tool.
8124  *  \param [in] eps - precision used to detect coincident mesh entities.
8125  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8126  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8127  *         this array using decrRef() as it is no more needed.
8128  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8129  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8130  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8131  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8132  *         it is no more needed.  
8133  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8134  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8135  *         is no more needed.  
8136  *  \throw If the coordinates array is not set in any of the meshes.
8137  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8138  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8139  */
8140 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8141 {
8142   m1->checkFullyDefined();
8143   m2->checkFullyDefined();
8144   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8146   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8147   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8148   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8149   std::vector<double> addCoo,addCoordsQuadratic;
8150   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8151   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8152   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8153                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8154   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8155   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8156   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8157   std::vector< std::vector<int> > intersectEdge2;
8158   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8159   subDiv2.clear(); dd5=0; dd6=0;
8160   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8161   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8162   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8163                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8164   //
8165   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8166   addCooDa->alloc((int)(addCoo.size())/2,2);
8167   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8168   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8169   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8170   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8171   std::vector<const DataArrayDouble *> coordss(4);
8172   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8173   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8174   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8179   ret->setConnectivity(conn,connI,true);
8180   ret->setCoords(coo);
8181   cellNb1=c1.retn(); cellNb2=c2.retn();
8182   return ret.retn();
8183 }
8184
8185 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8186                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8187                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8188                                                          const std::vector<double>& addCoords,
8189                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8190 {
8191   static const int SPACEDIM=2;
8192   std::vector<double> bbox1,bbox2;
8193   const double *coo1=m1->getCoords()->getConstPointer();
8194   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8195   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8196   int offset1=m1->getNumberOfNodes();
8197   const double *coo2=m2->getCoords()->getConstPointer();
8198   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8199   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8200   int offset2=offset1+m2->getNumberOfNodes();
8201   int offset3=offset2+((int)addCoords.size())/2;
8202   m1->getBoundingBoxForBBTree(bbox1);
8203   m2->getBoundingBoxForBBTree(bbox2);
8204   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8205   int ncell1=m1->getNumberOfCells();
8206   crI.push_back(0);
8207   for(int i=0;i<ncell1;i++)
8208     {
8209       std::vector<int> candidates2;
8210       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8211       std::map<INTERP_KERNEL::Node *,int> mapp;
8212       std::map<int,INTERP_KERNEL::Node *> mappRev;
8213       INTERP_KERNEL::QuadraticPolygon pol1;
8214       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8215       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8216       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8217       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8218                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8219       //
8220       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
8221       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8222       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8223       for(it1.first();!it1.finished();it1.next())
8224         edges1.insert(it1.current()->getPtr());
8225       //
8226       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8227       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8228       int ii=0;
8229       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8230         {
8231           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8232           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8233           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8234           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8235                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8236         }
8237       ii=0;
8238       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8239         {
8240           pol1.initLocationsWithOther(pol2s[ii]);
8241           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8242           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8243           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8244         }
8245       if(!edges1.empty())
8246         {
8247           try
8248             {
8249               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8250             }
8251           catch(INTERP_KERNEL::Exception& e)
8252             {
8253               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();
8254               throw INTERP_KERNEL::Exception(oss.str().c_str());
8255             }
8256         }
8257       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8258         (*it).second->decrRef();
8259     }
8260 }
8261
8262 /*!
8263  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8264  * 
8265  */
8266 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8267                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8268                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8269                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8270                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8271 {
8272   static const int SPACEDIM=2;
8273   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8274   desc2=DataArrayInt::New();
8275   descIndx2=DataArrayInt::New();
8276   revDesc2=DataArrayInt::New();
8277   revDescIndx2=DataArrayInt::New();
8278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8280   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8281   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8282   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8283   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8284   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8285   std::vector<double> bbox1,bbox2;
8286   m1Desc->getBoundingBoxForBBTree(bbox1);
8287   m2Desc->getBoundingBoxForBBTree(bbox2);
8288   int ncell1=m1Desc->getNumberOfCells();
8289   int ncell2=m2Desc->getNumberOfCells();
8290   intersectEdge1.resize(ncell1);
8291   colinear2.resize(ncell2);
8292   subDiv2.resize(ncell2);
8293   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8294   std::vector<int> candidates1(1);
8295   int offset1=m1->getNumberOfNodes();
8296   int offset2=offset1+m2->getNumberOfNodes();
8297   for(int i=0;i<ncell1;i++)
8298     {
8299       std::vector<int> candidates2;
8300       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8301       if(!candidates2.empty())
8302         {
8303           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8304           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8305           candidates1[0]=i;
8306           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8307           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8308           delete pol2;
8309           delete pol1;
8310         }
8311       else
8312         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8313     }
8314   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8315   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8316 }
8317
8318 /*!
8319  * This method performs the 2nd step of Partition of 2D mesh.
8320  * This method has 4 inputs :
8321  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8322  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8323  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8324  * 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'
8325  * \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'
8326  * \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.
8327  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8328  */
8329 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)
8330 {
8331   int offset1=m1->getNumberOfNodes();
8332   int ncell=m2->getNumberOfCells();
8333   const int *c=m2->getNodalConnectivity()->getConstPointer();
8334   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8335   const double *coo=m2->getCoords()->getConstPointer();
8336   const double *cooBis=m1->getCoords()->getConstPointer();
8337   int offset2=offset1+m2->getNumberOfNodes();
8338   intersectEdge.resize(ncell);
8339   for(int i=0;i<ncell;i++,cI++)
8340     {
8341       const std::vector<int>& divs=subDiv[i];
8342       int nnode=cI[1]-cI[0]-1;
8343       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8344       std::map<INTERP_KERNEL::Node *, int> mapp22;
8345       for(int j=0;j<nnode;j++)
8346         {
8347           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8348           int nnid=c[(*cI)+j+1];
8349           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8350           mapp22[nn]=nnid+offset1;
8351         }
8352       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8353       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8354         ((*it).second.first)->decrRef();
8355       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8356       std::map<INTERP_KERNEL::Node *,int> mapp3;
8357       for(std::size_t j=0;j<divs.size();j++)
8358         {
8359           int id=divs[j];
8360           INTERP_KERNEL::Node *tmp=0;
8361           if(id<offset1)
8362             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8363           else if(id<offset2)
8364             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8365           else
8366             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8367           addNodes[j]=tmp;
8368           mapp3[tmp]=id;
8369         }
8370       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8371       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8372         (*it)->decrRef();
8373       e->decrRef();
8374     }
8375 }
8376
8377 /*!
8378  * 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).
8379  * 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
8380  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8381  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8382  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8383  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8384  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8385  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8386  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8387  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8388  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8389  * \param [out] cut3DSuf input/output param.
8390  */
8391 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8392                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8393                                                    const int *desc, const int *descIndx, 
8394                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8395 {
8396   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8397   int nbOf3DSurfCell=(int)cut3DSurf.size();
8398   for(int i=0;i<nbOf3DSurfCell;i++)
8399     {
8400       std::vector<int> res;
8401       int offset=descIndx[i];
8402       int nbOfSeg=descIndx[i+1]-offset;
8403       for(int j=0;j<nbOfSeg;j++)
8404         {
8405           int edgeId=desc[offset+j];
8406           int status=cut3DCurve[edgeId];
8407           if(status!=-2)
8408             {
8409               if(status>-1)
8410                 res.push_back(status);
8411               else
8412                 {
8413                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8414                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8415                 }
8416             }
8417         }
8418       switch(res.size())
8419         {
8420         case 2:
8421           {
8422             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8423             break;
8424           }
8425         case 1:
8426         case 0:
8427           {
8428             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8429             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8430             if(res.size()==2)
8431               {
8432                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8433               }
8434             else
8435               {
8436                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8437               }
8438             break;
8439           }
8440         default:
8441           {// case when plane is on a multi colinear edge of a polyhedron
8442             if((int)res.size()==2*nbOfSeg)
8443               {
8444                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8445               }
8446             else
8447               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8448           }
8449         }
8450     }
8451 }
8452
8453 /*!
8454  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8455  * 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).
8456  * 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
8457  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8458  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8459  * \param desc is the descending connectivity 3D->3DSurf
8460  * \param descIndx is the descending connectivity index 3D->3DSurf
8461  */
8462 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8463                                                   const int *desc, const int *descIndx,
8464                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8465 {
8466   checkFullyDefined();
8467   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8469   const int *nodal3D=_nodal_connec->getConstPointer();
8470   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8471   int nbOfCells=getNumberOfCells();
8472   for(int i=0;i<nbOfCells;i++)
8473     {
8474       std::map<int, std::set<int> > m;
8475       int offset=descIndx[i];
8476       int nbOfFaces=descIndx[i+1]-offset;
8477       int start=-1;
8478       int end=-1;
8479       for(int j=0;j<nbOfFaces;j++)
8480         {
8481           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8482           if(p.first!=-1 && p.second!=-1)
8483             {
8484               if(p.first!=-2)
8485                 {
8486                   start=p.first; end=p.second;
8487                   m[p.first].insert(p.second);
8488                   m[p.second].insert(p.first);
8489                 }
8490               else
8491                 {
8492                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8493                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8494                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8495                   INTERP_KERNEL::NormalizedCellType cmsId;
8496                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8497                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8498                   for(unsigned k=0;k<nbOfNodesSon;k++)
8499                     {
8500                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8501                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8502                     }
8503                 }
8504             }
8505         }
8506       if(m.empty())
8507         continue;
8508       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8509       int prev=end;
8510       while(end!=start)
8511         {
8512           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8513           const std::set<int>& s=(*it).second;
8514           std::set<int> s2; s2.insert(prev);
8515           std::set<int> s3;
8516           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8517           if(s3.size()==1)
8518             {
8519               int val=*s3.begin();
8520               conn.push_back(start);
8521               prev=start;
8522               start=val;
8523             }
8524           else
8525             start=end;
8526         }
8527       conn.push_back(end);
8528       if(conn.size()>3)
8529         {
8530           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8531           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8532           cellIds->pushBackSilent(i);
8533         }
8534     }
8535 }
8536
8537 /*!
8538  * 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
8539  * 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
8540  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8541  * 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
8542  * 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.
8543  * 
8544  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8545  */
8546 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8547 {
8548   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8549   if(sz>=4)
8550     {
8551       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8552       if(cm.getDimension()==2)
8553         {
8554           const int *node=nodalConnBg+1;
8555           int startNode=*node++;
8556           double refX=coords[2*startNode];
8557           for(;node!=nodalConnEnd;node++)
8558             {
8559               if(coords[2*(*node)]<refX)
8560                 {
8561                   startNode=*node;
8562                   refX=coords[2*startNode];
8563                 }
8564             }
8565           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8566           refX=1e300;
8567           double tmp1;
8568           double tmp2[2];
8569           double angle0=-M_PI/2;
8570           //
8571           int nextNode=-1;
8572           int prevNode=-1;
8573           double resRef;
8574           double angleNext=0.;
8575           while(nextNode!=startNode)
8576             {
8577               nextNode=-1;
8578               resRef=1e300;
8579               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8580                 {
8581                   if(*node!=tmpOut.back() && *node!=prevNode)
8582                     {
8583                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8584                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8585                       double res;
8586                       if(angleM<=angle0)
8587                         res=angle0-angleM;
8588                       else
8589                         res=angle0-angleM+2.*M_PI;
8590                       if(res<resRef)
8591                         {
8592                           nextNode=*node;
8593                           resRef=res;
8594                           angleNext=angleM;
8595                         }
8596                     }
8597                 }
8598               if(nextNode!=startNode)
8599                 {
8600                   angle0=angleNext-M_PI;
8601                   if(angle0<-M_PI)
8602                     angle0+=2*M_PI;
8603                   prevNode=tmpOut.back();
8604                   tmpOut.push_back(nextNode);
8605                 }
8606             }
8607           std::vector<int> tmp3(2*(sz-1));
8608           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8609           std::copy(nodalConnBg+1,nodalConnEnd,it);
8610           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8611             {
8612               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8613               return false;
8614             }
8615           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8616             {
8617               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8618               return false;
8619             }
8620           else
8621             {
8622               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8623               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8624               return true;
8625             }
8626         }
8627       else
8628         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8629     }
8630   else
8631     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8632 }
8633
8634 /*!
8635  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8636  * 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.
8637  * 
8638  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8639  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8640  * \param [in,out] arr array in which the remove operation will be done.
8641  * \param [in,out] arrIndx array in the remove operation will modify
8642  * \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])
8643  * \return true if \b arr and \b arrIndx have been modified, false if not.
8644  */
8645 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8646 {
8647   if(!arrIndx || !arr)
8648     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8649   if(offsetForRemoval<0)
8650     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8651   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8652   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8653   int *arrIPtr=arrIndx->getPointer();
8654   *arrIPtr++=0;
8655   int previousArrI=0;
8656   const int *arrPtr=arr->getConstPointer();
8657   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8658   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8659     {
8660       if(*arrIPtr-previousArrI>offsetForRemoval)
8661         {
8662           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8663             {
8664               if(s.find(*work)==s.end())
8665                 arrOut.push_back(*work);
8666             }
8667         }
8668       previousArrI=*arrIPtr;
8669       *arrIPtr=(int)arrOut.size();
8670     }
8671   if(arr->getNumberOfTuples()==(int)arrOut.size())
8672     return false;
8673   arr->alloc((int)arrOut.size(),1);
8674   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8675   return true;
8676 }
8677
8678 /*!
8679  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8680  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8681  * The selection of extraction is done standardly in new2old format.
8682  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8683  *
8684  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8685  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8686  * \param [in] arrIn arr origin array from which the extraction will be done.
8687  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8688  * \param [out] arrOut the resulting array
8689  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8690  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8691  */
8692 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8693                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8694 {
8695   if(!arrIn || !arrIndxIn)
8696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8697   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8698   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8700   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8701   const int *arrInPtr=arrIn->getConstPointer();
8702   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8703   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8704   if(nbOfGrps<0)
8705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8706   int maxSizeOfArr=arrIn->getNumberOfTuples();
8707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8708   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8709   arrIo->alloc((int)(sz+1),1);
8710   const int *idsIt=idsOfSelectBg;
8711   int *work=arrIo->getPointer();
8712   *work++=0;
8713   int lgth=0;
8714   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8715     {
8716       if(*idsIt>=0 && *idsIt<nbOfGrps)
8717         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8718       else
8719         {
8720           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8721           throw INTERP_KERNEL::Exception(oss.str().c_str());
8722         }
8723       if(lgth>=work[-1])
8724         *work=lgth;
8725       else
8726         {
8727           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8728           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8729           throw INTERP_KERNEL::Exception(oss.str().c_str());
8730         }
8731     }
8732   arro->alloc(lgth,1);
8733   work=arro->getPointer();
8734   idsIt=idsOfSelectBg;
8735   for(std::size_t i=0;i<sz;i++,idsIt++)
8736     {
8737       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8738         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8739       else
8740         {
8741           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8742           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8743           throw INTERP_KERNEL::Exception(oss.str().c_str());
8744         }
8745     }
8746   arrOut=arro.retn();
8747   arrIndexOut=arrIo.retn();
8748 }
8749
8750 /*!
8751  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8752  * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
8753  * The selection of extraction is done standardly in new2old format.
8754  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8755  *
8756  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8757  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8758  * \param [in] arrIn arr origin array from which the extraction will be done.
8759  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8760  * \param [out] arrOut the resulting array
8761  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8762  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8763  */
8764 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8765                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8766 {
8767   if(!arrIn || !arrIndxIn)
8768     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8769   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8770   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8772   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8773   const int *arrInPtr=arrIn->getConstPointer();
8774   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8775   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8776   if(nbOfGrps<0)
8777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8778   int maxSizeOfArr=arrIn->getNumberOfTuples();
8779   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8781   arrIo->alloc((int)(sz+1),1);
8782   int idsIt=idsOfSelectStart;
8783   int *work=arrIo->getPointer();
8784   *work++=0;
8785   int lgth=0;
8786   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8787     {
8788       if(idsIt>=0 && idsIt<nbOfGrps)
8789         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8790       else
8791         {
8792           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8793           throw INTERP_KERNEL::Exception(oss.str().c_str());
8794         }
8795       if(lgth>=work[-1])
8796         *work=lgth;
8797       else
8798         {
8799           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8800           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8801           throw INTERP_KERNEL::Exception(oss.str().c_str());
8802         }
8803     }
8804   arro->alloc(lgth,1);
8805   work=arro->getPointer();
8806   idsIt=idsOfSelectStart;
8807   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8808     {
8809       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8810         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8811       else
8812         {
8813           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8814           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8815           throw INTERP_KERNEL::Exception(oss.str().c_str());
8816         }
8817     }
8818   arrOut=arro.retn();
8819   arrIndexOut=arrIo.retn();
8820 }
8821
8822 /*!
8823  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8824  * 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
8825  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8826  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8827  *
8828  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8829  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8830  * \param [in] arrIn arr origin array from which the extraction will be done.
8831  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8832  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8833  * \param [in] srcArrIndex index array of \b srcArr
8834  * \param [out] arrOut the resulting array
8835  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8836  * 
8837  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8838  */
8839 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8840                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8841                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8842 {
8843   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8844     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8847   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8848   std::vector<bool> v(nbOfTuples,true);
8849   int offset=0;
8850   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8851   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8852   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8853     {
8854       if(*it>=0 && *it<nbOfTuples)
8855         {
8856           v[*it]=false;
8857           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8858         }
8859       else
8860         {
8861           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8862           throw INTERP_KERNEL::Exception(oss.str().c_str());
8863         }
8864     }
8865   srcArrIndexPtr=srcArrIndex->getConstPointer();
8866   arrIo->alloc(nbOfTuples+1,1);
8867   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8868   const int *arrInPtr=arrIn->getConstPointer();
8869   const int *srcArrPtr=srcArr->getConstPointer();
8870   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8871   int *arroPtr=arro->getPointer();
8872   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8873     {
8874       if(v[ii])
8875         {
8876           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8877           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8878         }
8879       else
8880         {
8881           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8882           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8883           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8884         }
8885     }
8886   arrOut=arro.retn();
8887   arrIndexOut=arrIo.retn();
8888 }
8889
8890 /*!
8891  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8892  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8893  *
8894  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8895  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8896  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8897  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8898  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8899  * \param [in] srcArrIndex index array of \b srcArr
8900  * 
8901  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8902  */
8903 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8904                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8905 {
8906   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8908   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8909   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8910   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8911   int *arrInOutPtr=arrInOut->getPointer();
8912   const int *srcArrPtr=srcArr->getConstPointer();
8913   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8914     {
8915       if(*it>=0 && *it<nbOfTuples)
8916         {
8917           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8918             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8919           else
8920             {
8921               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] !";
8922               throw INTERP_KERNEL::Exception(oss.str().c_str());
8923             }
8924         }
8925       else
8926         {
8927           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8928           throw INTERP_KERNEL::Exception(oss.str().c_str());
8929         }
8930     }
8931 }
8932
8933 /*!
8934  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8935  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8936  * 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]].
8937  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8938  * A negative value in \b arrIn means that it is ignored.
8939  * 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.
8940  * 
8941  * \param [in] arrIn arr origin array from which the extraction will be done.
8942  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8943  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8944  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8945  */
8946 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8947 {
8948   int seed=0,nbOfDepthPeelingPerformed=0;
8949   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8950 }
8951
8952 /*!
8953  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8954  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8955  * 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]].
8956  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8957  * A negative value in \b arrIn means that it is ignored.
8958  * 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.
8959  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8960  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8961  * \param [in] arrIn arr origin array from which the extraction will be done.
8962  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8963  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8964  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8965  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8966  * \sa MEDCouplingUMesh::partitionBySpreadZone
8967  */
8968 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8969 {
8970   nbOfDepthPeelingPerformed=0;
8971   if(!arrIndxIn)
8972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8973   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8974   if(nbOfTuples<=0)
8975     {
8976       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8977       return ret;
8978     }
8979   //
8980   std::vector<bool> fetched(nbOfTuples,false);
8981   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8982 }
8983
8984 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)
8985 {
8986   nbOfDepthPeelingPerformed=0;
8987   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8989   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8990   std::vector<bool> fetched2(nbOfTuples,false);
8991   int i=0;
8992   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8993     {
8994       if(*seedElt>=0 && *seedElt<nbOfTuples)
8995         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8996       else
8997         { 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()); }
8998     }
8999   const int *arrInPtr=arrIn->getConstPointer();
9000   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9001   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9002   std::vector<int> idsToFetch1(seedBg,seedEnd);
9003   std::vector<int> idsToFetch2;
9004   std::vector<int> *idsToFetch=&idsToFetch1;
9005   std::vector<int> *idsToFetchOther=&idsToFetch2;
9006   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9007     {
9008       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9009         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9010           if(!fetched[*it2])
9011             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9012       std::swap(idsToFetch,idsToFetchOther);
9013       idsToFetchOther->clear();
9014       nbOfDepthPeelingPerformed++;
9015     }
9016   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9017   i=0;
9018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9019   int *retPtr=ret->getPointer();
9020   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9021     if(*it)
9022       *retPtr++=i;
9023   return ret.retn();
9024 }
9025
9026 /*!
9027  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9028  * 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
9029  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9030  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9031  *
9032  * \param [in] start begin of set of ids of the input extraction (included)
9033  * \param [in] end end of set of ids of the input extraction (excluded)
9034  * \param [in] step step of the set of ids in range mode.
9035  * \param [in] arrIn arr origin array from which the extraction will be done.
9036  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9037  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9038  * \param [in] srcArrIndex index array of \b srcArr
9039  * \param [out] arrOut the resulting array
9040  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9041  * 
9042  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9043  */
9044 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9045                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9046                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9047 {
9048   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9051   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9052   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9053   int offset=0;
9054   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9055   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9056   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9057   int it=start;
9058   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9059     {
9060       if(it>=0 && it<nbOfTuples)
9061         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9062       else
9063         {
9064           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9065           throw INTERP_KERNEL::Exception(oss.str().c_str());
9066         }
9067     }
9068   srcArrIndexPtr=srcArrIndex->getConstPointer();
9069   arrIo->alloc(nbOfTuples+1,1);
9070   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9071   const int *arrInPtr=arrIn->getConstPointer();
9072   const int *srcArrPtr=srcArr->getConstPointer();
9073   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9074   int *arroPtr=arro->getPointer();
9075   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9076     {
9077       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9078       if(pos<0)
9079         {
9080           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9081           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9082         }
9083       else
9084         {
9085           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9086           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9087         }
9088     }
9089   arrOut=arro.retn();
9090   arrIndexOut=arrIo.retn();
9091 }
9092
9093 /*!
9094  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9095  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9096  *
9097  * \param [in] start begin of set of ids of the input extraction (included)
9098  * \param [in] end end of set of ids of the input extraction (excluded)
9099  * \param [in] step step of the set of ids in range mode.
9100  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9101  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9102  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9103  * \param [in] srcArrIndex index array of \b srcArr
9104  * 
9105  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9106  */
9107 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9108                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9109 {
9110   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9112   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9113   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9114   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9115   int *arrInOutPtr=arrInOut->getPointer();
9116   const int *srcArrPtr=srcArr->getConstPointer();
9117   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9118   int it=start;
9119   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9120     {
9121       if(it>=0 && it<nbOfTuples)
9122         {
9123           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9124             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9125           else
9126             {
9127               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9128               throw INTERP_KERNEL::Exception(oss.str().c_str());
9129             }
9130         }
9131       else
9132         {
9133           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9134           throw INTERP_KERNEL::Exception(oss.str().c_str());
9135         }
9136     }
9137 }
9138
9139 /*!
9140  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9141  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9142  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9143  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9144  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9145  * 
9146  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9147  */
9148 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9149 {
9150   checkFullyDefined();
9151   int mdim=getMeshDimension();
9152   int spaceDim=getSpaceDimension();
9153   if(mdim!=spaceDim)
9154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9155   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9156   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9157   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9158   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9159   ret->setCoords(getCoords());
9160   ret->allocateCells((int)partition.size());
9161   //
9162   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9163     {
9164       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9165       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9166       switch(mdim)
9167         {
9168         case 2:
9169           cell=tmp->buildUnionOf2DMesh();
9170           break;
9171         case 3:
9172           cell=tmp->buildUnionOf3DMesh();
9173           break;
9174         default:
9175           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9176         }
9177       
9178       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9179     }
9180   //
9181   ret->finishInsertingCells();
9182   return ret.retn();
9183 }
9184
9185 /*!
9186  * This method partitions \b this into contiguous zone.
9187  * This method only needs a well defined connectivity. Coordinates are not considered here.
9188  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9189  */
9190 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9191 {
9192   //#if 0
9193   int nbOfCellsCur=getNumberOfCells();
9194   std::vector<DataArrayInt *> ret;
9195   if(nbOfCellsCur<=0)
9196     return ret;
9197   DataArrayInt *neigh=0,*neighI=0;
9198   computeNeighborsOfCells(neigh,neighI);
9199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9200   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9201   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9202   int seed=0;
9203   while(seed<nbOfCellsCur)
9204     {
9205       int nbOfPeelPerformed=0;
9206       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9207       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9208     }
9209   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9210     ret.push_back((*it).retn());
9211   return ret;
9212   //#endif
9213 #if 0
9214   int nbOfCellsCur=getNumberOfCells();
9215   DataArrayInt *neigh=0,*neighI=0;
9216   computeNeighborsOfCells(neigh,neighI);
9217   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9219   std::vector<DataArrayInt *> ret;
9220   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9221   while(nbOfCellsCur>0)
9222     {
9223       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9224       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9225       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9226       ret2.push_back(tmp2);  ret.push_back(tmp2);
9227       nbOfCellsCur=tmp3->getNumberOfTuples();
9228       if(nbOfCellsCur>0)
9229         {
9230           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9231           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9232           neighAuto=neigh;
9233           neighIAuto=neighI;
9234           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9235           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9236         }
9237     }
9238   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9239     (*it)->incrRef();
9240   return ret;
9241 #endif
9242 }
9243
9244 /*!
9245  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9246  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9247  *
9248  * \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.
9249  * \return a newly allocated DataArrayInt to be managed by the caller.
9250  * \throw In case of \a code has not the right format (typically of size 3*n)
9251  */
9252 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9253 {
9254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9255   std::size_t nb=code.size()/3;
9256   if(code.size()%3!=0)
9257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9258   ret->alloc((int)nb,2);
9259   int *retPtr=ret->getPointer();
9260   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9261     {
9262       retPtr[0]=code[3*i+2];
9263       retPtr[1]=code[3*i+2]+code[3*i+1];
9264     }
9265   return ret.retn();
9266 }
9267
9268 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9269                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9270 {
9271   if(mesh)
9272     {
9273       mesh->incrRef();
9274       _nb_cell=mesh->getNumberOfCells();
9275     }
9276 }
9277
9278 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9279 {
9280   if(_mesh)
9281     _mesh->decrRef();
9282   if(_own_cell)
9283     delete _cell;
9284 }
9285
9286 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9287                                                                                                                                _own_cell(false),_cell_id(bg-1),
9288                                                                                                                                _nb_cell(end)
9289 {
9290   if(mesh)
9291     mesh->incrRef();
9292 }
9293
9294 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9295 {
9296   _cell_id++;
9297   if(_cell_id<_nb_cell)
9298     {
9299       _cell->next();
9300       return _cell;
9301     }
9302   else
9303     return 0;
9304 }
9305
9306 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9307 {
9308   if(_mesh)
9309     _mesh->incrRef();
9310 }
9311
9312 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9313 {
9314   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9315 }
9316
9317 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9318 {
9319   if(_mesh)
9320     _mesh->decrRef();
9321 }
9322
9323 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9324                                                                                                                                                                   _itc(itc),
9325                                                                                                                                                                   _bg(bg),_end(end)
9326 {
9327   if(_mesh)
9328     _mesh->incrRef();
9329 }
9330
9331 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9332 {
9333   if(_mesh)
9334     _mesh->decrRef();
9335 }
9336
9337 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9338 {
9339   return _type;
9340 }
9341
9342 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9343 {
9344   return _end-_bg;
9345 }
9346
9347 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9348 {
9349   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9350 }
9351
9352 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9353 {
9354   if(mesh)
9355     {
9356       mesh->incrRef();
9357       _nb_cell=mesh->getNumberOfCells();
9358     }
9359 }
9360
9361 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9362 {
9363   if(_mesh)
9364     _mesh->decrRef();
9365   delete _cell;
9366 }
9367
9368 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9369 {
9370   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9371   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9372   if(_cell_id<_nb_cell)
9373     {
9374       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9375       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9376       int startId=_cell_id;
9377       _cell_id+=nbOfElems;
9378       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9379     }
9380   else
9381     return 0;
9382 }
9383
9384 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9385 {
9386   if(mesh)
9387     {
9388       _conn=mesh->getNodalConnectivity()->getPointer();
9389       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9390     }
9391 }
9392
9393 void MEDCouplingUMeshCell::next()
9394 {
9395   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9396     {
9397       _conn+=_conn_lgth;
9398       _conn_indx++;
9399     }
9400   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9401 }
9402
9403 std::string MEDCouplingUMeshCell::repr() const
9404 {
9405   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9406     {
9407       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9408       oss << " : ";
9409       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9410       return oss.str();
9411     }
9412   else
9413     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9414 }
9415
9416 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9417 {
9418   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9419     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9420   else
9421     return INTERP_KERNEL::NORM_ERROR;
9422 }
9423
9424 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9425 {
9426   lgth=_conn_lgth;
9427   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9428     return _conn;
9429   else
9430     return 0;
9431 }