]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/MEDCoupling/MEDCouplingUMesh.cxx
Salome HOME
nearly ready for the single geo type in MEDLoader
[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   int typi=(int)typ;
6697   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6698   ret->setCoords(getCoords());
6699   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6700   if(retC)
6701     {
6702       int nbCells=getNumberOfCells();
6703       int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6704       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6705       int *outPtr=connOut->getPointer();
6706       const int *conn=_nodal_connec->begin();
6707       const int *connI=_nodal_connec_index->begin();
6708       nbNodesPerCell++;
6709       for(int i=0;i<nbCells;i++,connI++)
6710         {
6711           if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6712             outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6713           else
6714             {
6715               std::ostringstream oss; oss << "MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6716               throw INTERP_KERNEL::Exception(oss.str().c_str());
6717             }
6718         }
6719       retC->setNodalConnectivity(connOut);
6720     }
6721   else
6722     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6723   return ret.retn();
6724 }
6725
6726 /*!
6727  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6728  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6729  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6730  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6731  * are not used here to avoid the build of big permutation array.
6732  *
6733  * \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
6734  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6735  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6736  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6737  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6738  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6739  * \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
6740  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6741  */
6742 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6743                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6744                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6745 {
6746   std::vector<const MEDCouplingUMesh *> ms2;
6747   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6748     if(*it)
6749       {
6750         (*it)->checkConnectivityFullyDefined();
6751         ms2.push_back(*it);
6752       }
6753   if(ms2.empty())
6754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6755   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6756   int meshDim=ms2[0]->getMeshDimension();
6757   std::vector<const MEDCouplingUMesh *> m1ssm;
6758   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6759   //
6760   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6761   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6762   int fake=0,rk=0;
6763   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6764   ret1->alloc(0,1); ret2->alloc(0,1);
6765   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6766     {
6767       if(meshDim!=(*it)->getMeshDimension())
6768         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6769       if(refCoo!=(*it)->getCoords())
6770         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6771       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6772       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6773       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6774       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6775         {
6776           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6777           m1ssmSingleAuto.push_back(singleCell);
6778           m1ssmSingle.push_back(singleCell);
6779           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6780         }
6781     }
6782   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6784   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6785   for(std::size_t i=0;i<m1ssm.size();i++)
6786     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6787   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6788   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6789   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6790   return ret0.retn();
6791 }
6792
6793 /*!
6794  * This method returns a newly created DataArrayInt instance.
6795  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6796  */
6797 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6798 {
6799   checkFullyDefined();
6800   const int *conn=_nodal_connec->getConstPointer();
6801   const int *connIndex=_nodal_connec_index->getConstPointer();
6802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6803   for(const int *w=begin;w!=end;w++)
6804     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6805       ret->pushBackSilent(*w);
6806   return ret.retn();
6807 }
6808
6809 /*!
6810  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6811  * are in [0:getNumberOfCells())
6812  */
6813 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6814 {
6815   checkFullyDefined();
6816   const int *conn=_nodal_connec->getConstPointer();
6817   const int *connI=_nodal_connec_index->getConstPointer();
6818   int nbOfCells=getNumberOfCells();
6819   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6820   int *tmp=new int[nbOfCells];
6821   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6822     {
6823       int j=0;
6824       for(const int *i=connI;i!=connI+nbOfCells;i++)
6825         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6826           tmp[std::distance(connI,i)]=j++;
6827     }
6828   DataArrayInt *ret=DataArrayInt::New();
6829   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6830   ret->copyStringInfoFrom(*da);
6831   int *retPtr=ret->getPointer();
6832   const int *daPtr=da->getConstPointer();
6833   int nbOfElems=da->getNbOfElems();
6834   for(int k=0;k<nbOfElems;k++)
6835     retPtr[k]=tmp[daPtr[k]];
6836   delete [] tmp;
6837   return ret;
6838 }
6839
6840 /*!
6841  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6842  * This method \b works \b for mesh sorted by type.
6843  * cells whose ids is in 'idsPerGeoType' array.
6844  * This method conserves coords and name of mesh.
6845  */
6846 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6847 {
6848   std::vector<int> code=getDistributionOfTypes();
6849   std::size_t nOfTypesInThis=code.size()/3;
6850   int sz=0,szOfType=0;
6851   for(std::size_t i=0;i<nOfTypesInThis;i++)
6852     {
6853       if(code[3*i]!=type)
6854         sz+=code[3*i+1];
6855       else
6856         szOfType=code[3*i+1];
6857     }
6858   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6859     if(*work<0 || *work>=szOfType)
6860       {
6861         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6862         oss << ". It should be in [0," << szOfType << ") !";
6863         throw INTERP_KERNEL::Exception(oss.str().c_str());
6864       }
6865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6866   int *idsPtr=idsTokeep->getPointer();
6867   int offset=0;
6868   for(std::size_t i=0;i<nOfTypesInThis;i++)
6869     {
6870       if(code[3*i]!=type)
6871         for(int j=0;j<code[3*i+1];j++)
6872           *idsPtr++=offset+j;
6873       else
6874         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6875       offset+=code[3*i+1];
6876     }
6877   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6878   ret->copyTinyInfoFrom(this);
6879   return ret.retn();
6880 }
6881
6882 /*!
6883  * This method returns a vector of size 'this->getNumberOfCells()'.
6884  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6885  */
6886 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6887 {
6888   int ncell=getNumberOfCells();
6889   std::vector<bool> ret(ncell);
6890   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6891   const int *c=getNodalConnectivity()->getConstPointer();
6892   for(int i=0;i<ncell;i++)
6893     {
6894       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6895       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6896       ret[i]=cm.isQuadratic();
6897     }
6898   return ret;
6899 }
6900
6901 /*!
6902  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6903  */
6904 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6905 {
6906   if(other->getType()!=UNSTRUCTURED)
6907     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6908   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6909   return MergeUMeshes(this,otherC);
6910 }
6911
6912 /*!
6913  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6914  * computed by averaging coordinates of cell nodes, so this method is not a right
6915  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6916  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6917  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6918  *          components. The caller is to delete this array using decrRef() as it is
6919  *          no more needed.
6920  *  \throw If the coordinates array is not set.
6921  *  \throw If the nodal connectivity of cells is not defined.
6922  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6923  */
6924 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6925 {
6926   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6927   int spaceDim=getSpaceDimension();
6928   int nbOfCells=getNumberOfCells();
6929   ret->alloc(nbOfCells,spaceDim);
6930   ret->copyStringInfoFrom(*getCoords());
6931   double *ptToFill=ret->getPointer();
6932   const int *nodal=_nodal_connec->getConstPointer();
6933   const int *nodalI=_nodal_connec_index->getConstPointer();
6934   const double *coor=_coords->getConstPointer();
6935   for(int i=0;i<nbOfCells;i++)
6936     {
6937       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6938       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6939       ptToFill+=spaceDim;
6940     }
6941   return ret.retn();
6942 }
6943
6944 /*!
6945  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6946  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
6947  * 
6948  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6949  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6950  * 
6951  * \sa MEDCouplingUMesh::getBarycenterAndOwner
6952  * \throw If \a this is not fully defined (coordinates and connectivity)
6953  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6954  */
6955 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
6956 {
6957   checkFullyDefined();
6958   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6959   int spaceDim=getSpaceDimension();
6960   int nbOfCells=getNumberOfCells();
6961   int nbOfNodes=getNumberOfNodes();
6962   ret->alloc(nbOfCells,spaceDim);
6963   double *ptToFill=ret->getPointer();
6964   const int *nodal=_nodal_connec->getConstPointer();
6965   const int *nodalI=_nodal_connec_index->getConstPointer();
6966   const double *coor=_coords->getConstPointer();
6967   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6968     {
6969       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6970       std::fill(ptToFill,ptToFill+spaceDim,0.);
6971       if(type!=INTERP_KERNEL::NORM_POLYHED)
6972         {
6973           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6974             {
6975               if(*conn>=0 && *conn<nbOfNodes)
6976                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6977               else
6978                 {
6979                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6980                   throw INTERP_KERNEL::Exception(oss.str().c_str());
6981                 }
6982             }
6983           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6984           if(nbOfNodesInCell>0)
6985             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6986           else
6987             {
6988               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6989               throw INTERP_KERNEL::Exception(oss.str().c_str());
6990             }
6991         }
6992       else
6993         {
6994           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6995           s.erase(-1);
6996           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6997             {
6998               if(*it>=0 && *it<nbOfNodes)
6999                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7000               else
7001                 {
7002                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7003                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7004                 }
7005             }
7006           if(!s.empty())
7007             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7008           else
7009             {
7010               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7011               throw INTERP_KERNEL::Exception(oss.str().c_str());
7012             }
7013         }
7014     }
7015   return ret.retn();
7016 }
7017
7018 /*!
7019  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7020  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7021  * are specified via an array of cell ids. 
7022  *  \warning Validity of the specified cell ids is not checked! 
7023  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7024  *  \param [in] begin - an array of cell ids of interest.
7025  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7026  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7027  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7028  *          caller is to delete this array using decrRef() as it is no more needed. 
7029  *  \throw If the coordinates array is not set.
7030  *  \throw If the nodal connectivity of cells is not defined.
7031  *
7032  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7033  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7034  */
7035 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7036 {
7037   DataArrayDouble *ret=DataArrayDouble::New();
7038   int spaceDim=getSpaceDimension();
7039   int nbOfTuple=(int)std::distance(begin,end);
7040   ret->alloc(nbOfTuple,spaceDim);
7041   double *ptToFill=ret->getPointer();
7042   double *tmp=new double[spaceDim];
7043   const int *nodal=_nodal_connec->getConstPointer();
7044   const int *nodalI=_nodal_connec_index->getConstPointer();
7045   const double *coor=_coords->getConstPointer();
7046   for(const int *w=begin;w!=end;w++)
7047     {
7048       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7049       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7050       ptToFill+=spaceDim;
7051     }
7052   delete [] tmp;
7053   return ret;
7054 }
7055
7056 /*!
7057  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7058  * 
7059  */
7060 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7061 {
7062   if(!da)
7063     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7064   da->checkAllocated();
7065   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7066   ret->setCoords(da);
7067   int nbOfTuples=da->getNumberOfTuples();
7068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7070   c->alloc(2*nbOfTuples,1);
7071   cI->alloc(nbOfTuples+1,1);
7072   int *cp=c->getPointer();
7073   int *cip=cI->getPointer();
7074   *cip++=0;
7075   for(int i=0;i<nbOfTuples;i++)
7076     {
7077       *cp++=INTERP_KERNEL::NORM_POINT1;
7078       *cp++=i;
7079       *cip++=2*(i+1);
7080     }
7081   ret->setConnectivity(c,cI,true);
7082   return ret.retn();
7083 }
7084 /*!
7085  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7086  * Cells and nodes of
7087  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7088  *  \param [in] mesh1 - the first mesh.
7089  *  \param [in] mesh2 - the second mesh.
7090  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7091  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7092  *          is no more needed.
7093  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7094  *  \throw If the coordinates array is not set in none of the meshes.
7095  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7096  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7097  */
7098 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7099 {
7100   std::vector<const MEDCouplingUMesh *> tmp(2);
7101   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7102   return MergeUMeshes(tmp);
7103 }
7104
7105 /*!
7106  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7107  * Cells and nodes of
7108  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7109  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7110  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7111  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7112  *          is no more needed.
7113  *  \throw If \a a.size() == 0.
7114  *  \throw If \a a[ *i* ] == NULL.
7115  *  \throw If the coordinates array is not set in none of the meshes.
7116  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7117  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7118 */
7119 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7120 {
7121   std::size_t sz=a.size();
7122   if(sz==0)
7123     return MergeUMeshesLL(a);
7124   for(std::size_t ii=0;ii<sz;ii++)
7125     if(!a[ii])
7126       {
7127         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7128         throw INTERP_KERNEL::Exception(oss.str().c_str());
7129       }
7130   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7131   std::vector< const MEDCouplingUMesh * > aa(sz);
7132   int spaceDim=-3;
7133   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7134     {
7135       const MEDCouplingUMesh *cur=a[i];
7136       const DataArrayDouble *coo=cur->getCoords();
7137       if(coo)
7138         spaceDim=coo->getNumberOfComponents();
7139     }
7140   if(spaceDim==-3)
7141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7142   for(std::size_t i=0;i<sz;i++)
7143     {
7144       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7145       aa[i]=bb[i];
7146     }
7147   return MergeUMeshesLL(aa);
7148 }
7149
7150 /// @cond INTERNAL
7151
7152 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7153 {
7154   if(a.empty())
7155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7156   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7157   int meshDim=(*it)->getMeshDimension();
7158   int nbOfCells=(*it)->getNumberOfCells();
7159   int meshLgth=(*it++)->getMeshLength();
7160   for(;it!=a.end();it++)
7161     {
7162       if(meshDim!=(*it)->getMeshDimension())
7163         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7164       nbOfCells+=(*it)->getNumberOfCells();
7165       meshLgth+=(*it)->getMeshLength();
7166     }
7167   std::vector<const MEDCouplingPointSet *> aps(a.size());
7168   std::copy(a.begin(),a.end(),aps.begin());
7169   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7170   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7171   ret->setCoords(pts);
7172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7173   c->alloc(meshLgth,1);
7174   int *cPtr=c->getPointer();
7175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7176   cI->alloc(nbOfCells+1,1);
7177   int *cIPtr=cI->getPointer();
7178   *cIPtr++=0;
7179   int offset=0;
7180   int offset2=0;
7181   for(it=a.begin();it!=a.end();it++)
7182     {
7183       int curNbOfCell=(*it)->getNumberOfCells();
7184       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7185       const int *curC=(*it)->_nodal_connec->getConstPointer();
7186       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7187       for(int j=0;j<curNbOfCell;j++)
7188         {
7189           const int *src=curC+curCI[j];
7190           *cPtr++=*src++;
7191           for(;src!=curC+curCI[j+1];src++,cPtr++)
7192             {
7193               if(*src!=-1)
7194                 *cPtr=*src+offset2;
7195               else
7196                 *cPtr=-1;
7197             }
7198         }
7199       offset+=curCI[curNbOfCell];
7200       offset2+=(*it)->getNumberOfNodes();
7201     }
7202   //
7203   ret->setConnectivity(c,cI,true);
7204   return ret.retn();
7205 }
7206
7207 /// @endcond
7208
7209 /*!
7210  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7211  * dimension and sharing the node coordinates array.
7212  * All cells of the first mesh precede all cells of the second mesh
7213  * within the result mesh. 
7214  *  \param [in] mesh1 - the first mesh.
7215  *  \param [in] mesh2 - the second mesh.
7216  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7217  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7218  *          is no more needed.
7219  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7220  *  \throw If the meshes do not share the node coordinates array.
7221  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7222  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7223  */
7224 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7225 {
7226   std::vector<const MEDCouplingUMesh *> tmp(2);
7227   tmp[0]=mesh1; tmp[1]=mesh2;
7228   return MergeUMeshesOnSameCoords(tmp);
7229 }
7230
7231 /*!
7232  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7233  * dimension and sharing the node coordinates array.
7234  * All cells of the *i*-th mesh precede all cells of the
7235  * (*i*+1)-th mesh within the result mesh.
7236  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7237  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7238  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7239  *          is no more needed.
7240  *  \throw If \a a.size() == 0.
7241  *  \throw If \a a[ *i* ] == NULL.
7242  *  \throw If the meshes do not share the node coordinates array.
7243  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7244  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7245  */
7246 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7247 {
7248   if(meshes.empty())
7249     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7250   for(std::size_t ii=0;ii<meshes.size();ii++)
7251     if(!meshes[ii])
7252       {
7253         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7254         throw INTERP_KERNEL::Exception(oss.str().c_str());
7255       }
7256   const DataArrayDouble *coords=meshes.front()->getCoords();
7257   int meshDim=meshes.front()->getMeshDimension();
7258   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7259   int meshLgth=0;
7260   int meshIndexLgth=0;
7261   for(;iter!=meshes.end();iter++)
7262     {
7263       if(coords!=(*iter)->getCoords())
7264         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7265       if(meshDim!=(*iter)->getMeshDimension())
7266         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7267       meshLgth+=(*iter)->getMeshLength();
7268       meshIndexLgth+=(*iter)->getNumberOfCells();
7269     }
7270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7271   nodal->alloc(meshLgth,1);
7272   int *nodalPtr=nodal->getPointer();
7273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7274   nodalIndex->alloc(meshIndexLgth+1,1);
7275   int *nodalIndexPtr=nodalIndex->getPointer();
7276   int offset=0;
7277   for(iter=meshes.begin();iter!=meshes.end();iter++)
7278     {
7279       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7280       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7281       int nbOfCells=(*iter)->getNumberOfCells();
7282       int meshLgth2=(*iter)->getMeshLength();
7283       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7284       if(iter!=meshes.begin())
7285         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7286       else
7287         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7288       offset+=meshLgth2;
7289     }
7290   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7291   ret->setName("merge");
7292   ret->setMeshDimension(meshDim);
7293   ret->setConnectivity(nodal,nodalIndex,true);
7294   ret->setCoords(coords);
7295   return ret;
7296 }
7297
7298 /*!
7299  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7300  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7301  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7302  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7303  * New" mode are returned for each input mesh.
7304  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7305  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7306  *          valid values [0,1,2], see zipConnectivityTraducer().
7307  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7308  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7309  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7310  *          no more needed.
7311  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7312  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7313  *          is no more needed.
7314  *  \throw If \a meshes.size() == 0.
7315  *  \throw If \a meshes[ *i* ] == NULL.
7316  *  \throw If the meshes do not share the node coordinates array.
7317  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7318  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7319  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7320  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7321  */
7322 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7323 {
7324   //All checks are delegated to MergeUMeshesOnSameCoords
7325   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7326   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7327   corr.resize(meshes.size());
7328   std::size_t nbOfMeshes=meshes.size();
7329   int offset=0;
7330   const int *o2nPtr=o2n->getConstPointer();
7331   for(std::size_t i=0;i<nbOfMeshes;i++)
7332     {
7333       DataArrayInt *tmp=DataArrayInt::New();
7334       int curNbOfCells=meshes[i]->getNumberOfCells();
7335       tmp->alloc(curNbOfCells,1);
7336       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7337       offset+=curNbOfCells;
7338       tmp->setName(meshes[i]->getName());
7339       corr[i]=tmp;
7340     }
7341   return ret.retn();
7342 }
7343
7344 /*!
7345  * Makes all given meshes share the nodal connectivity array. The common connectivity
7346  * array is created by concatenating the connectivity arrays of all given meshes. All
7347  * the given meshes must be of the same space dimension but dimension of cells **can
7348  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7349  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7350  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7351  *  \param [in,out] meshes - a vector of meshes to update.
7352  *  \throw If any of \a meshes is NULL.
7353  *  \throw If the coordinates array is not set in any of \a meshes.
7354  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7355  *  \throw If \a meshes are of different space dimension.
7356  */
7357 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7358 {
7359   std::size_t sz=meshes.size();
7360   if(sz==0 || sz==1)
7361     return;
7362   std::vector< const DataArrayDouble * > coords(meshes.size());
7363   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7364   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7365     {
7366       if((*it))
7367         {
7368           (*it)->checkConnectivityFullyDefined();
7369           const DataArrayDouble *coo=(*it)->getCoords();
7370           if(coo)
7371             *it2=coo;
7372           else
7373             {
7374               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7375               oss << " has no coordinate array defined !";
7376               throw INTERP_KERNEL::Exception(oss.str().c_str());
7377             }
7378         }
7379       else
7380         {
7381           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7382           oss << " is null !";
7383           throw INTERP_KERNEL::Exception(oss.str().c_str());
7384         }
7385     }
7386   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7387   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7388   int offset=(*it)->getNumberOfNodes();
7389   (*it++)->setCoords(res);
7390   for(;it!=meshes.end();it++)
7391     {
7392       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7393       (*it)->setCoords(res);
7394       (*it)->shiftNodeNumbersInConn(offset);
7395       offset+=oldNumberOfNodes;
7396     }
7397 }
7398
7399 /*!
7400  * Merges nodes coincident with a given precision within all given meshes that share
7401  * the nodal connectivity array. The given meshes **can be of different** mesh
7402  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7403  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7404  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7405  *  \param [in,out] meshes - a vector of meshes to update.
7406  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7407  *  \throw If any of \a meshes is NULL.
7408  *  \throw If the \a meshes do not share the same node coordinates array.
7409  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7410  */
7411 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7412 {
7413   if(meshes.empty())
7414     return ;
7415   std::set<const DataArrayDouble *> s;
7416   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7417     {
7418       if(*it)
7419         s.insert((*it)->getCoords());
7420       else
7421         {
7422           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 !";
7423           throw INTERP_KERNEL::Exception(oss.str().c_str());
7424         }
7425     }
7426   if(s.size()!=1)
7427     {
7428       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 !";
7429       throw INTERP_KERNEL::Exception(oss.str().c_str());
7430     }
7431   const DataArrayDouble *coo=*(s.begin());
7432   if(!coo)
7433     return;
7434   //
7435   DataArrayInt *comm,*commI;
7436   coo->findCommonTuples(eps,-1,comm,commI);
7437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7438   int oldNbOfNodes=coo->getNumberOfTuples();
7439   int newNbOfNodes;
7440   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7441   if(oldNbOfNodes==newNbOfNodes)
7442     return ;
7443   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7444   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7445     {
7446       (*it)->renumberNodesInConn(o2n->getConstPointer());
7447       (*it)->setCoords(newCoords);
7448     } 
7449 }
7450
7451 /*!
7452  * 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.
7453  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7454  * \param isQuad specifies the policy of connectivity.
7455  * @ret in/out parameter in which the result will be append
7456  */
7457 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7458 {
7459   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7460   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7461   ret.push_back(cm.getExtrudedType());
7462   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7463   switch(flatType)
7464     {
7465     case INTERP_KERNEL::NORM_POINT1:
7466       {
7467         ret.push_back(connBg[1]);
7468         ret.push_back(connBg[1]+nbOfNodesPerLev);
7469         break;
7470       }
7471     case INTERP_KERNEL::NORM_SEG2:
7472       {
7473         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7474         ret.insert(ret.end(),conn,conn+4);
7475         break;
7476       }
7477     case INTERP_KERNEL::NORM_SEG3:
7478       {
7479         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7480         ret.insert(ret.end(),conn,conn+8);
7481         break;
7482       }
7483     case INTERP_KERNEL::NORM_QUAD4:
7484       {
7485         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7486         ret.insert(ret.end(),conn,conn+8);
7487         break;
7488       }
7489     case INTERP_KERNEL::NORM_TRI3:
7490       {
7491         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7492         ret.insert(ret.end(),conn,conn+6);
7493         break;
7494       }
7495     case INTERP_KERNEL::NORM_TRI6:
7496       {
7497         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,
7498                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7499         ret.insert(ret.end(),conn,conn+15);
7500         break;
7501       }
7502     case INTERP_KERNEL::NORM_QUAD8:
7503       {
7504         int conn[20]={
7505           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7506           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7507           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7508         };
7509         ret.insert(ret.end(),conn,conn+20);
7510         break;
7511       }
7512     case INTERP_KERNEL::NORM_POLYGON:
7513       {
7514         std::back_insert_iterator< std::vector<int> > ii(ret);
7515         std::copy(connBg+1,connEnd,ii);
7516         *ii++=-1;
7517         std::reverse_iterator<const int *> rConnBg(connEnd);
7518         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7519         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7520         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7521         for(std::size_t i=0;i<nbOfRadFaces;i++)
7522           {
7523             *ii++=-1;
7524             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7525             std::copy(conn,conn+4,ii);
7526           }
7527         break;
7528       }
7529     default:
7530       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7531     }
7532 }
7533
7534 /*!
7535  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7536  */
7537 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7538 {
7539   double v[3]={0.,0.,0.};
7540   std::size_t sz=std::distance(begin,end);
7541   if(isQuadratic)
7542     sz/=2;
7543   for(std::size_t i=0;i<sz;i++)
7544     {
7545       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];
7546       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7547       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7548     }
7549   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7550 }
7551
7552 /*!
7553  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7554  */
7555 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7556 {
7557   std::vector<std::pair<int,int> > edges;
7558   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7559   const int *bgFace=begin;
7560   for(std::size_t i=0;i<nbOfFaces;i++)
7561     {
7562       const int *endFace=std::find(bgFace+1,end,-1);
7563       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7564       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7565         {
7566           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7567           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7568             return false;
7569           edges.push_back(p1);
7570         }
7571       bgFace=endFace+1;
7572     }
7573   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7574 }
7575
7576 /*!
7577  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7578  */
7579 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7580 {
7581   double vec0[3],vec1[3];
7582   std::size_t sz=std::distance(begin,end);
7583   if(sz%2!=0)
7584     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7585   int nbOfNodes=(int)sz/2;
7586   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7587   const double *pt0=coords+3*begin[0];
7588   const double *pt1=coords+3*begin[nbOfNodes];
7589   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7590   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7591 }
7592
7593 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7594 {
7595   std::size_t sz=std::distance(begin,end);
7596   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7597   std::size_t nbOfNodes(sz/2);
7598   std::copy(begin,end,(int *)tmp);
7599   for(std::size_t j=1;j<nbOfNodes;j++)
7600     {
7601       begin[j]=tmp[nbOfNodes-j];
7602       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7603     }
7604 }
7605
7606 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7607 {
7608   std::size_t sz=std::distance(begin,end);
7609   if(sz!=4)
7610     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7611   double vec0[3],vec1[3];
7612   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7613   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]; 
7614   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;
7615 }
7616
7617 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7618 {
7619   std::size_t sz=std::distance(begin,end);
7620   if(sz!=5)
7621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7622   double vec0[3];
7623   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7624   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7625   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7626 }
7627
7628 /*!
7629  * 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 ) 
7630  * 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
7631  * a 2D space.
7632  *
7633  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7634  * \param [in] coords the coordinates with nb of components exactly equal to 3
7635  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7636  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7637  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7638  */
7639 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7640 {
7641   int nbFaces=std::count(begin+1,end,-1)+1;
7642   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7643   double *vPtr=v->getPointer();
7644   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7645   double *pPtr=p->getPointer();
7646   const int *stFaceConn=begin+1;
7647   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7648     {
7649       const int *endFaceConn=std::find(stFaceConn,end,-1);
7650       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7651       stFaceConn=endFaceConn+1;
7652     }
7653   pPtr=p->getPointer(); vPtr=v->getPointer();
7654   DataArrayInt *comm1=0,*commI1=0;
7655   v->findCommonTuples(eps,-1,comm1,commI1);
7656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7657   const int *comm1Ptr=comm1->getConstPointer();
7658   const int *commI1Ptr=commI1->getConstPointer();
7659   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7660   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7661   //
7662   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7663   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7664   mm->finishInsertingCells();
7665   //
7666   for(int i=0;i<nbOfGrps1;i++)
7667     {
7668       int vecId=comm1Ptr[commI1Ptr[i]];
7669       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7670       DataArrayInt *comm2=0,*commI2=0;
7671       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7672       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7673       const int *comm2Ptr=comm2->getConstPointer();
7674       const int *commI2Ptr=commI2->getConstPointer();
7675       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7676       for(int j=0;j<nbOfGrps2;j++)
7677         {
7678           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7679             {
7680               res->insertAtTheEnd(begin,end);
7681               res->pushBackSilent(-1);
7682             }
7683           else
7684             {
7685               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7686               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7687               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7688               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7689               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7690               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7691               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7692               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7693               const int *idsNodePtr=idsNode->getConstPointer();
7694               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];
7695               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7696               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7697               if(std::abs(norm)>eps)
7698                 {
7699                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7700                   mm3->rotate(center,vec,angle);
7701                 }
7702               mm3->changeSpaceDimension(2);
7703               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7704               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7705               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7706               int nbOfCells=mm4->getNumberOfCells();
7707               for(int k=0;k<nbOfCells;k++)
7708                 {
7709                   int l=0;
7710                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7711                     res->pushBackSilent(idsNodePtr[*work]);
7712                   res->pushBackSilent(-1);
7713                 }
7714             }
7715         }
7716     }
7717   res->popBackSilent();
7718 }
7719
7720 /*!
7721  * 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
7722  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7723  * 
7724  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7725  * \param [in] coords coordinates expected to have 3 components.
7726  * \param [in] begin start of the nodal connectivity of the face.
7727  * \param [in] end end of the nodal connectivity (excluded) of the face.
7728  * \param [out] v the normalized vector of size 3
7729  * \param [out] p the pos of plane
7730  */
7731 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7732 {
7733   std::size_t nbPoints=std::distance(begin,end);
7734   if(nbPoints<3)
7735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7736   double vec[3]={0.,0.,0.};
7737   std::size_t j=0;
7738   bool refFound=false;
7739   for(;j<nbPoints-1 && !refFound;j++)
7740     {
7741       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7742       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7743       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7744       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7745       if(norm>eps)
7746         {
7747           refFound=true;
7748           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7749         }
7750     }
7751   for(std::size_t i=j;i<nbPoints-1;i++)
7752     {
7753       double curVec[3];
7754       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7755       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7756       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7757       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7758       if(norm<eps)
7759         continue;
7760       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7761       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];
7762       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7763       if(norm>eps)
7764         {
7765           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7766           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7767           return ;
7768         }
7769     }
7770   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7771 }
7772
7773 /*!
7774  * This method tries to obtain a well oriented polyhedron.
7775  * If the algorithm fails, an exception will be thrown.
7776  */
7777 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7778 {
7779   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7780   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7781   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7782   isPerm[0]=true;
7783   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7784   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7785   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7786   //
7787   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7788     {
7789       bgFace=begin;
7790       std::size_t smthChanged=0;
7791       for(std::size_t i=0;i<nbOfFaces;i++)
7792         {
7793           endFace=std::find(bgFace+1,end,-1);
7794           nbOfEdgesInFace=std::distance(bgFace,endFace);
7795           if(!isPerm[i])
7796             {
7797               bool b;
7798               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7799                 {
7800                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7801                   std::pair<int,int> p2(p1.second,p1.first);
7802                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7803                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7804                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7805                 }
7806               if(isPerm[i])
7807                 { 
7808                   if(!b)
7809                     std::reverse(bgFace+1,endFace);
7810                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7811                     {
7812                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7813                       std::pair<int,int> p2(p1.second,p1.first);
7814                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7815                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7816                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7817                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7818                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7819                       if(it!=edgesOK.end())
7820                         {
7821                           edgesOK.erase(it);
7822                           edgesFinished.push_back(p1);
7823                         }
7824                       else
7825                         edgesOK.push_back(p1);
7826                     }
7827                 }
7828             }
7829           bgFace=endFace+1;
7830         }
7831       if(smthChanged==0)
7832         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7833     }
7834   if(!edgesOK.empty())
7835     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7836   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7837     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7838       bgFace=begin;
7839       for(std::size_t i=0;i<nbOfFaces;i++)
7840         {
7841           endFace=std::find(bgFace+1,end,-1);
7842           std::reverse(bgFace+1,endFace);
7843           bgFace=endFace+1;
7844         }
7845     }
7846 }
7847
7848 /*!
7849  * This method makes the assumption spacedimension == meshdimension == 2.
7850  * This method works only for linear cells.
7851  * 
7852  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7853  */
7854 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7855 {
7856   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7858   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7860   int nbOfNodesExpected=m->getNumberOfNodes();
7861   if(m->getNumberOfCells()!=nbOfNodesExpected)
7862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7864   const int *n2oPtr=n2o->getConstPointer();
7865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7866   m->getReverseNodalConnectivity(revNodal,revNodalI);
7867   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7868   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7869   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7871   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7872   if(nbOfNodesExpected<1)
7873     return ret.retn();
7874   int prevCell=0;
7875   int prevNode=nodalPtr[nodalIPtr[0]+1];
7876   *work++=n2oPtr[prevNode];
7877   for(int i=1;i<nbOfNodesExpected;i++)
7878     {
7879       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7880         {
7881           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7882           conn.erase(prevNode);
7883           if(conn.size()==1)
7884             {
7885               int curNode=*(conn.begin());
7886               *work++=n2oPtr[curNode];
7887               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7888               shar.erase(prevCell);
7889               if(shar.size()==1)
7890                 {
7891                   prevCell=*(shar.begin());
7892                   prevNode=curNode;
7893                 }
7894               else
7895                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7896             }
7897           else
7898             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7899         }
7900       else
7901         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7902     }
7903   return ret.retn();
7904 }
7905
7906 /*!
7907  * This method makes the assumption spacedimension == meshdimension == 3.
7908  * This method works only for linear cells.
7909  * 
7910  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7911  */
7912 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7913 {
7914   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7916   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7917   const int *conn=m->getNodalConnectivity()->getConstPointer();
7918   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7919   int nbOfCells=m->getNumberOfCells();
7920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7921   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7922   if(nbOfCells<1)
7923     return ret.retn();
7924   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7925   for(int i=1;i<nbOfCells;i++)
7926     {
7927       *work++=-1;
7928       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7929     }
7930   return ret.retn();
7931 }
7932
7933 /*!
7934  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7935  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7936  */
7937 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7938 {
7939   double *w=zipFrmt;
7940   if(spaceDim==3)
7941     for(int i=0;i<nbOfNodesInCell;i++)
7942       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7943   else if(spaceDim==2)
7944     {
7945       for(int i=0;i<nbOfNodesInCell;i++)
7946         {
7947           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7948           *w++=0.;
7949         }
7950     }
7951   else
7952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7953 }
7954
7955 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7956 {
7957   int nbOfCells=getNumberOfCells();
7958   if(nbOfCells<=0)
7959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7960   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};
7961   ofs << "  <" << getVTKDataSetType() << ">\n";
7962   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7963   ofs << "      <PointData>\n" << pointData << std::endl;
7964   ofs << "      </PointData>\n";
7965   ofs << "      <CellData>\n" << cellData << std::endl;
7966   ofs << "      </CellData>\n";
7967   ofs << "      <Points>\n";
7968   if(getSpaceDimension()==3)
7969     _coords->writeVTK(ofs,8,"Points");
7970   else
7971     {
7972       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7973       coo->writeVTK(ofs,8,"Points");
7974     }
7975   ofs << "      </Points>\n";
7976   ofs << "      <Cells>\n";
7977   const int *cPtr=_nodal_connec->getConstPointer();
7978   const int *cIPtr=_nodal_connec_index->getConstPointer();
7979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7983   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7984   int szFaceOffsets=0,szConn=0;
7985   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7986     {
7987       *w2=cPtr[cIPtr[i]];
7988       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7989         {
7990           *w1=-1;
7991           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7992           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7993         }
7994       else
7995         {
7996           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7997           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7998           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7999           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8000           w4=std::copy(c.begin(),c.end(),w4);
8001         }
8002     }
8003   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8004   types->writeVTK(ofs,8,"UInt8","types");
8005   offsets->writeVTK(ofs,8,"Int32","offsets");
8006   if(szFaceOffsets!=0)
8007     {//presence of Polyhedra
8008       connectivity->reAlloc(szConn);
8009       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8010       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8011       w1=faces->getPointer();
8012       for(int i=0;i<nbOfCells;i++)
8013         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8014           {
8015             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8016             *w1++=nbFaces;
8017             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8018             for(int j=0;j<nbFaces;j++)
8019               {
8020                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8021                 *w1++=(int)std::distance(w6,w5);
8022                 w1=std::copy(w6,w5,w1);
8023                 w6=w5+1;
8024               }
8025           }
8026       faces->writeVTK(ofs,8,"Int32","faces");
8027     }
8028   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8029   ofs << "      </Cells>\n";
8030   ofs << "    </Piece>\n";
8031   ofs << "  </" << getVTKDataSetType() << ">\n";
8032 }
8033
8034 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8035 {
8036   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8037   if(_mesh_dim==-2)
8038     { stream << " Not set !"; return ; }
8039   stream << " Mesh dimension : " << _mesh_dim << ".";
8040   if(_mesh_dim==-1)
8041     return ;
8042   if(!_coords)
8043     { stream << " No coordinates set !"; return ; }
8044   if(!_coords->isAllocated())
8045     { stream << " Coordinates set but not allocated !"; return ; }
8046   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8047   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8048   if(!_nodal_connec_index)
8049     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8050   if(!_nodal_connec_index->isAllocated())
8051     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8052   int lgth=_nodal_connec_index->getNumberOfTuples();
8053   int cpt=_nodal_connec_index->getNumberOfComponents();
8054   if(cpt!=1 || lgth<1)
8055     return ;
8056   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8057 }
8058
8059 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8060 {
8061   return std::string("UnstructuredGrid");
8062 }
8063
8064 /*!
8065  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8066  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8067  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8068  * meshes.
8069  *  \param [in] m1 - the first input mesh which is a partitioned object.
8070  *  \param [in] m2 - the second input mesh which is a partition tool.
8071  *  \param [in] eps - precision used to detect coincident mesh entities.
8072  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8073  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8074  *         this array using decrRef() as it is no more needed.
8075  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8076  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8077  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8078  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8079  *         it is no more needed.  
8080  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8081  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8082  *         is no more needed.  
8083  *  \throw If the coordinates array is not set in any of the meshes.
8084  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8085  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8086  */
8087 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8088 {
8089   m1->checkFullyDefined();
8090   m2->checkFullyDefined();
8091   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8093   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8094   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8095   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8096   std::vector<double> addCoo,addCoordsQuadratic;
8097   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8098   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8099   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8100                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8101   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8103   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8104   std::vector< std::vector<int> > intersectEdge2;
8105   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8106   subDiv2.clear(); dd5=0; dd6=0;
8107   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8108   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8109   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8110                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8111   //
8112   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8113   addCooDa->alloc((int)(addCoo.size())/2,2);
8114   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8115   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8116   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8117   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8118   std::vector<const DataArrayDouble *> coordss(4);
8119   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8120   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8121   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8123   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8126   ret->setConnectivity(conn,connI,true);
8127   ret->setCoords(coo);
8128   cellNb1=c1.retn(); cellNb2=c2.retn();
8129   return ret.retn();
8130 }
8131
8132 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8133                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8134                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8135                                                          const std::vector<double>& addCoords,
8136                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8137 {
8138   static const int SPACEDIM=2;
8139   std::vector<double> bbox1,bbox2;
8140   const double *coo1=m1->getCoords()->getConstPointer();
8141   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8142   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8143   int offset1=m1->getNumberOfNodes();
8144   const double *coo2=m2->getCoords()->getConstPointer();
8145   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8146   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8147   int offset2=offset1+m2->getNumberOfNodes();
8148   int offset3=offset2+((int)addCoords.size())/2;
8149   m1->getBoundingBoxForBBTree(bbox1);
8150   m2->getBoundingBoxForBBTree(bbox2);
8151   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8152   int ncell1=m1->getNumberOfCells();
8153   crI.push_back(0);
8154   for(int i=0;i<ncell1;i++)
8155     {
8156       std::vector<int> candidates2;
8157       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8158       std::map<INTERP_KERNEL::Node *,int> mapp;
8159       std::map<int,INTERP_KERNEL::Node *> mappRev;
8160       INTERP_KERNEL::QuadraticPolygon pol1;
8161       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8162       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8163       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8164       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8165                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8166       //
8167       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
8168       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8169       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8170       for(it1.first();!it1.finished();it1.next())
8171         edges1.insert(it1.current()->getPtr());
8172       //
8173       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8174       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8175       int ii=0;
8176       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8177         {
8178           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8179           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8180           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8181           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8182                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8183         }
8184       ii=0;
8185       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8186         {
8187           pol1.initLocationsWithOther(pol2s[ii]);
8188           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8189           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8190           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8191         }
8192       if(!edges1.empty())
8193         {
8194           try
8195             {
8196               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8197             }
8198           catch(INTERP_KERNEL::Exception& e)
8199             {
8200               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();
8201               throw INTERP_KERNEL::Exception(oss.str().c_str());
8202             }
8203         }
8204       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8205         (*it).second->decrRef();
8206     }
8207 }
8208
8209 /*!
8210  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8211  * 
8212  */
8213 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8214                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8215                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8216                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8217                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8218 {
8219   static const int SPACEDIM=2;
8220   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8221   desc2=DataArrayInt::New();
8222   descIndx2=DataArrayInt::New();
8223   revDesc2=DataArrayInt::New();
8224   revDescIndx2=DataArrayInt::New();
8225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8227   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8228   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8229   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8230   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8231   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8232   std::vector<double> bbox1,bbox2;
8233   m1Desc->getBoundingBoxForBBTree(bbox1);
8234   m2Desc->getBoundingBoxForBBTree(bbox2);
8235   int ncell1=m1Desc->getNumberOfCells();
8236   int ncell2=m2Desc->getNumberOfCells();
8237   intersectEdge1.resize(ncell1);
8238   colinear2.resize(ncell2);
8239   subDiv2.resize(ncell2);
8240   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8241   std::vector<int> candidates1(1);
8242   int offset1=m1->getNumberOfNodes();
8243   int offset2=offset1+m2->getNumberOfNodes();
8244   for(int i=0;i<ncell1;i++)
8245     {
8246       std::vector<int> candidates2;
8247       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8248       if(!candidates2.empty())
8249         {
8250           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8251           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8252           candidates1[0]=i;
8253           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8254           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8255           delete pol2;
8256           delete pol1;
8257         }
8258       else
8259         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8260     }
8261   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8262   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8263 }
8264
8265 /*!
8266  * This method performs the 2nd step of Partition of 2D mesh.
8267  * This method has 4 inputs :
8268  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8269  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8270  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8271  * 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'
8272  * \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'
8273  * \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.
8274  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8275  */
8276 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)
8277 {
8278   int offset1=m1->getNumberOfNodes();
8279   int ncell=m2->getNumberOfCells();
8280   const int *c=m2->getNodalConnectivity()->getConstPointer();
8281   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8282   const double *coo=m2->getCoords()->getConstPointer();
8283   const double *cooBis=m1->getCoords()->getConstPointer();
8284   int offset2=offset1+m2->getNumberOfNodes();
8285   intersectEdge.resize(ncell);
8286   for(int i=0;i<ncell;i++,cI++)
8287     {
8288       const std::vector<int>& divs=subDiv[i];
8289       int nnode=cI[1]-cI[0]-1;
8290       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8291       std::map<INTERP_KERNEL::Node *, int> mapp22;
8292       for(int j=0;j<nnode;j++)
8293         {
8294           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8295           int nnid=c[(*cI)+j+1];
8296           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8297           mapp22[nn]=nnid+offset1;
8298         }
8299       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8300       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8301         ((*it).second.first)->decrRef();
8302       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8303       std::map<INTERP_KERNEL::Node *,int> mapp3;
8304       for(std::size_t j=0;j<divs.size();j++)
8305         {
8306           int id=divs[j];
8307           INTERP_KERNEL::Node *tmp=0;
8308           if(id<offset1)
8309             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8310           else if(id<offset2)
8311             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8312           else
8313             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8314           addNodes[j]=tmp;
8315           mapp3[tmp]=id;
8316         }
8317       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8318       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8319         (*it)->decrRef();
8320       e->decrRef();
8321     }
8322 }
8323
8324 /*!
8325  * 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).
8326  * 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
8327  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8328  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8329  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8330  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8331  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8332  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8333  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8334  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8335  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8336  * \param [out] cut3DSuf input/output param.
8337  */
8338 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8339                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8340                                                    const int *desc, const int *descIndx, 
8341                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8342 {
8343   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8344   int nbOf3DSurfCell=(int)cut3DSurf.size();
8345   for(int i=0;i<nbOf3DSurfCell;i++)
8346     {
8347       std::vector<int> res;
8348       int offset=descIndx[i];
8349       int nbOfSeg=descIndx[i+1]-offset;
8350       for(int j=0;j<nbOfSeg;j++)
8351         {
8352           int edgeId=desc[offset+j];
8353           int status=cut3DCurve[edgeId];
8354           if(status!=-2)
8355             {
8356               if(status>-1)
8357                 res.push_back(status);
8358               else
8359                 {
8360                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8361                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8362                 }
8363             }
8364         }
8365       switch(res.size())
8366         {
8367         case 2:
8368           {
8369             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8370             break;
8371           }
8372         case 1:
8373         case 0:
8374           {
8375             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8376             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8377             if(res.size()==2)
8378               {
8379                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8380               }
8381             else
8382               {
8383                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8384               }
8385             break;
8386           }
8387         default:
8388           {// case when plane is on a multi colinear edge of a polyhedron
8389             if((int)res.size()==2*nbOfSeg)
8390               {
8391                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8392               }
8393             else
8394               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8395           }
8396         }
8397     }
8398 }
8399
8400 /*!
8401  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8402  * 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).
8403  * 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
8404  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8405  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8406  * \param desc is the descending connectivity 3D->3DSurf
8407  * \param descIndx is the descending connectivity index 3D->3DSurf
8408  */
8409 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8410                                                   const int *desc, const int *descIndx,
8411                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8412 {
8413   checkFullyDefined();
8414   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8416   const int *nodal3D=_nodal_connec->getConstPointer();
8417   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8418   int nbOfCells=getNumberOfCells();
8419   for(int i=0;i<nbOfCells;i++)
8420     {
8421       std::map<int, std::set<int> > m;
8422       int offset=descIndx[i];
8423       int nbOfFaces=descIndx[i+1]-offset;
8424       int start=-1;
8425       int end=-1;
8426       for(int j=0;j<nbOfFaces;j++)
8427         {
8428           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8429           if(p.first!=-1 && p.second!=-1)
8430             {
8431               if(p.first!=-2)
8432                 {
8433                   start=p.first; end=p.second;
8434                   m[p.first].insert(p.second);
8435                   m[p.second].insert(p.first);
8436                 }
8437               else
8438                 {
8439                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8440                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8441                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8442                   INTERP_KERNEL::NormalizedCellType cmsId;
8443                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8444                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8445                   for(unsigned k=0;k<nbOfNodesSon;k++)
8446                     {
8447                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8448                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8449                     }
8450                 }
8451             }
8452         }
8453       if(m.empty())
8454         continue;
8455       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8456       int prev=end;
8457       while(end!=start)
8458         {
8459           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8460           const std::set<int>& s=(*it).second;
8461           std::set<int> s2; s2.insert(prev);
8462           std::set<int> s3;
8463           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8464           if(s3.size()==1)
8465             {
8466               int val=*s3.begin();
8467               conn.push_back(start);
8468               prev=start;
8469               start=val;
8470             }
8471           else
8472             start=end;
8473         }
8474       conn.push_back(end);
8475       if(conn.size()>3)
8476         {
8477           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8478           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8479           cellIds->pushBackSilent(i);
8480         }
8481     }
8482 }
8483
8484 /*!
8485  * 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
8486  * 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
8487  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8488  * 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
8489  * 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.
8490  * 
8491  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8492  */
8493 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8494 {
8495   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8496   if(sz>=4)
8497     {
8498       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8499       if(cm.getDimension()==2)
8500         {
8501           const int *node=nodalConnBg+1;
8502           int startNode=*node++;
8503           double refX=coords[2*startNode];
8504           for(;node!=nodalConnEnd;node++)
8505             {
8506               if(coords[2*(*node)]<refX)
8507                 {
8508                   startNode=*node;
8509                   refX=coords[2*startNode];
8510                 }
8511             }
8512           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8513           refX=1e300;
8514           double tmp1;
8515           double tmp2[2];
8516           double angle0=-M_PI/2;
8517           //
8518           int nextNode=-1;
8519           int prevNode=-1;
8520           double resRef;
8521           double angleNext=0.;
8522           while(nextNode!=startNode)
8523             {
8524               nextNode=-1;
8525               resRef=1e300;
8526               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8527                 {
8528                   if(*node!=tmpOut.back() && *node!=prevNode)
8529                     {
8530                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8531                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8532                       double res;
8533                       if(angleM<=angle0)
8534                         res=angle0-angleM;
8535                       else
8536                         res=angle0-angleM+2.*M_PI;
8537                       if(res<resRef)
8538                         {
8539                           nextNode=*node;
8540                           resRef=res;
8541                           angleNext=angleM;
8542                         }
8543                     }
8544                 }
8545               if(nextNode!=startNode)
8546                 {
8547                   angle0=angleNext-M_PI;
8548                   if(angle0<-M_PI)
8549                     angle0+=2*M_PI;
8550                   prevNode=tmpOut.back();
8551                   tmpOut.push_back(nextNode);
8552                 }
8553             }
8554           std::vector<int> tmp3(2*(sz-1));
8555           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8556           std::copy(nodalConnBg+1,nodalConnEnd,it);
8557           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8558             {
8559               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8560               return false;
8561             }
8562           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8563             {
8564               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8565               return false;
8566             }
8567           else
8568             {
8569               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8570               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8571               return true;
8572             }
8573         }
8574       else
8575         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8576     }
8577   else
8578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8579 }
8580
8581 /*!
8582  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8583  * 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.
8584  * 
8585  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8586  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8587  * \param [in,out] arr array in which the remove operation will be done.
8588  * \param [in,out] arrIndx array in the remove operation will modify
8589  * \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])
8590  * \return true if \b arr and \b arrIndx have been modified, false if not.
8591  */
8592 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8593 {
8594   if(!arrIndx || !arr)
8595     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8596   if(offsetForRemoval<0)
8597     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8598   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8599   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8600   int *arrIPtr=arrIndx->getPointer();
8601   *arrIPtr++=0;
8602   int previousArrI=0;
8603   const int *arrPtr=arr->getConstPointer();
8604   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8605   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8606     {
8607       if(*arrIPtr-previousArrI>offsetForRemoval)
8608         {
8609           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8610             {
8611               if(s.find(*work)==s.end())
8612                 arrOut.push_back(*work);
8613             }
8614         }
8615       previousArrI=*arrIPtr;
8616       *arrIPtr=(int)arrOut.size();
8617     }
8618   if(arr->getNumberOfTuples()==(int)arrOut.size())
8619     return false;
8620   arr->alloc((int)arrOut.size(),1);
8621   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8622   return true;
8623 }
8624
8625 /*!
8626  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8627  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8628  * The selection of extraction is done standardly in new2old format.
8629  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8630  *
8631  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8632  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8633  * \param [in] arrIn arr origin array from which the extraction will be done.
8634  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8635  * \param [out] arrOut the resulting array
8636  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8637  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8638  */
8639 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8640                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8641 {
8642   if(!arrIn || !arrIndxIn)
8643     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8644   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8645   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8646     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8647   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8648   const int *arrInPtr=arrIn->getConstPointer();
8649   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8650   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8651   if(nbOfGrps<0)
8652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8653   int maxSizeOfArr=arrIn->getNumberOfTuples();
8654   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8656   arrIo->alloc((int)(sz+1),1);
8657   const int *idsIt=idsOfSelectBg;
8658   int *work=arrIo->getPointer();
8659   *work++=0;
8660   int lgth=0;
8661   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8662     {
8663       if(*idsIt>=0 && *idsIt<nbOfGrps)
8664         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8665       else
8666         {
8667           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8668           throw INTERP_KERNEL::Exception(oss.str().c_str());
8669         }
8670       if(lgth>=work[-1])
8671         *work=lgth;
8672       else
8673         {
8674           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8675           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8676           throw INTERP_KERNEL::Exception(oss.str().c_str());
8677         }
8678     }
8679   arro->alloc(lgth,1);
8680   work=arro->getPointer();
8681   idsIt=idsOfSelectBg;
8682   for(std::size_t i=0;i<sz;i++,idsIt++)
8683     {
8684       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8685         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8686       else
8687         {
8688           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8689           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8690           throw INTERP_KERNEL::Exception(oss.str().c_str());
8691         }
8692     }
8693   arrOut=arro.retn();
8694   arrIndexOut=arrIo.retn();
8695 }
8696
8697 /*!
8698  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8699  * 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 ).
8700  * The selection of extraction is done standardly in new2old format.
8701  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8702  *
8703  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8704  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8705  * \param [in] arrIn arr origin array from which the extraction will be done.
8706  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8707  * \param [out] arrOut the resulting array
8708  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8709  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8710  */
8711 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8712                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8713 {
8714   if(!arrIn || !arrIndxIn)
8715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8716   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8717   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8718     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8719   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8720   const int *arrInPtr=arrIn->getConstPointer();
8721   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8722   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8723   if(nbOfGrps<0)
8724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8725   int maxSizeOfArr=arrIn->getNumberOfTuples();
8726   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8727   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8728   arrIo->alloc((int)(sz+1),1);
8729   int idsIt=idsOfSelectStart;
8730   int *work=arrIo->getPointer();
8731   *work++=0;
8732   int lgth=0;
8733   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8734     {
8735       if(idsIt>=0 && idsIt<nbOfGrps)
8736         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8737       else
8738         {
8739           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8740           throw INTERP_KERNEL::Exception(oss.str().c_str());
8741         }
8742       if(lgth>=work[-1])
8743         *work=lgth;
8744       else
8745         {
8746           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8747           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8748           throw INTERP_KERNEL::Exception(oss.str().c_str());
8749         }
8750     }
8751   arro->alloc(lgth,1);
8752   work=arro->getPointer();
8753   idsIt=idsOfSelectStart;
8754   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8755     {
8756       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8757         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8758       else
8759         {
8760           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8761           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8762           throw INTERP_KERNEL::Exception(oss.str().c_str());
8763         }
8764     }
8765   arrOut=arro.retn();
8766   arrIndexOut=arrIo.retn();
8767 }
8768
8769 /*!
8770  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8771  * 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
8772  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8773  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8774  *
8775  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8776  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8777  * \param [in] arrIn arr origin array from which the extraction will be done.
8778  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8779  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8780  * \param [in] srcArrIndex index array of \b srcArr
8781  * \param [out] arrOut the resulting array
8782  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8783  * 
8784  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8785  */
8786 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8787                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8788                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8789 {
8790   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8791     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8794   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8795   std::vector<bool> v(nbOfTuples,true);
8796   int offset=0;
8797   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8798   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8799   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8800     {
8801       if(*it>=0 && *it<nbOfTuples)
8802         {
8803           v[*it]=false;
8804           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8805         }
8806       else
8807         {
8808           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8809           throw INTERP_KERNEL::Exception(oss.str().c_str());
8810         }
8811     }
8812   srcArrIndexPtr=srcArrIndex->getConstPointer();
8813   arrIo->alloc(nbOfTuples+1,1);
8814   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8815   const int *arrInPtr=arrIn->getConstPointer();
8816   const int *srcArrPtr=srcArr->getConstPointer();
8817   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8818   int *arroPtr=arro->getPointer();
8819   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8820     {
8821       if(v[ii])
8822         {
8823           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8824           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8825         }
8826       else
8827         {
8828           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8829           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8830           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8831         }
8832     }
8833   arrOut=arro.retn();
8834   arrIndexOut=arrIo.retn();
8835 }
8836
8837 /*!
8838  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8839  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8840  *
8841  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8842  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8843  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8844  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8845  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8846  * \param [in] srcArrIndex index array of \b srcArr
8847  * 
8848  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8849  */
8850 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8851                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8852 {
8853   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8855   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8856   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8857   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8858   int *arrInOutPtr=arrInOut->getPointer();
8859   const int *srcArrPtr=srcArr->getConstPointer();
8860   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8861     {
8862       if(*it>=0 && *it<nbOfTuples)
8863         {
8864           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8865             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8866           else
8867             {
8868               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] !";
8869               throw INTERP_KERNEL::Exception(oss.str().c_str());
8870             }
8871         }
8872       else
8873         {
8874           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8875           throw INTERP_KERNEL::Exception(oss.str().c_str());
8876         }
8877     }
8878 }
8879
8880 /*!
8881  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8882  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8883  * 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]].
8884  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8885  * A negative value in \b arrIn means that it is ignored.
8886  * 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.
8887  * 
8888  * \param [in] arrIn arr origin array from which the extraction will be done.
8889  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8890  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8891  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8892  */
8893 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8894 {
8895   int seed=0,nbOfDepthPeelingPerformed=0;
8896   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8897 }
8898
8899 /*!
8900  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8901  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8902  * 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]].
8903  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8904  * A negative value in \b arrIn means that it is ignored.
8905  * 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.
8906  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8907  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8908  * \param [in] arrIn arr origin array from which the extraction will be done.
8909  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8910  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8911  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8912  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8913  * \sa MEDCouplingUMesh::partitionBySpreadZone
8914  */
8915 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8916 {
8917   nbOfDepthPeelingPerformed=0;
8918   if(!arrIndxIn)
8919     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8920   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8921   if(nbOfTuples<=0)
8922     {
8923       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8924       return ret;
8925     }
8926   //
8927   std::vector<bool> fetched(nbOfTuples,false);
8928   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8929 }
8930
8931 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)
8932 {
8933   nbOfDepthPeelingPerformed=0;
8934   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8935     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8936   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8937   std::vector<bool> fetched2(nbOfTuples,false);
8938   int i=0;
8939   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8940     {
8941       if(*seedElt>=0 && *seedElt<nbOfTuples)
8942         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8943       else
8944         { 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()); }
8945     }
8946   const int *arrInPtr=arrIn->getConstPointer();
8947   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8948   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8949   std::vector<int> idsToFetch1(seedBg,seedEnd);
8950   std::vector<int> idsToFetch2;
8951   std::vector<int> *idsToFetch=&idsToFetch1;
8952   std::vector<int> *idsToFetchOther=&idsToFetch2;
8953   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8954     {
8955       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8956         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8957           if(!fetched[*it2])
8958             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8959       std::swap(idsToFetch,idsToFetchOther);
8960       idsToFetchOther->clear();
8961       nbOfDepthPeelingPerformed++;
8962     }
8963   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8964   i=0;
8965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8966   int *retPtr=ret->getPointer();
8967   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8968     if(*it)
8969       *retPtr++=i;
8970   return ret.retn();
8971 }
8972
8973 /*!
8974  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8975  * 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
8976  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8977  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8978  *
8979  * \param [in] start begin of set of ids of the input extraction (included)
8980  * \param [in] end end of set of ids of the input extraction (excluded)
8981  * \param [in] step step of the set of ids in range mode.
8982  * \param [in] arrIn arr origin array from which the extraction will be done.
8983  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8984  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8985  * \param [in] srcArrIndex index array of \b srcArr
8986  * \param [out] arrOut the resulting array
8987  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8988  * 
8989  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8990  */
8991 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8992                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8993                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8994 {
8995   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8996     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8997   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8998   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8999   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9000   int offset=0;
9001   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9002   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9003   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9004   int it=start;
9005   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9006     {
9007       if(it>=0 && it<nbOfTuples)
9008         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9009       else
9010         {
9011           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9012           throw INTERP_KERNEL::Exception(oss.str().c_str());
9013         }
9014     }
9015   srcArrIndexPtr=srcArrIndex->getConstPointer();
9016   arrIo->alloc(nbOfTuples+1,1);
9017   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9018   const int *arrInPtr=arrIn->getConstPointer();
9019   const int *srcArrPtr=srcArr->getConstPointer();
9020   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9021   int *arroPtr=arro->getPointer();
9022   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9023     {
9024       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9025       if(pos<0)
9026         {
9027           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9028           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9029         }
9030       else
9031         {
9032           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9033           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9034         }
9035     }
9036   arrOut=arro.retn();
9037   arrIndexOut=arrIo.retn();
9038 }
9039
9040 /*!
9041  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9042  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9043  *
9044  * \param [in] start begin of set of ids of the input extraction (included)
9045  * \param [in] end end of set of ids of the input extraction (excluded)
9046  * \param [in] step step of the set of ids in range mode.
9047  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9048  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9049  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9050  * \param [in] srcArrIndex index array of \b srcArr
9051  * 
9052  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9053  */
9054 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9055                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9056 {
9057   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9058     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9059   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9060   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9061   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9062   int *arrInOutPtr=arrInOut->getPointer();
9063   const int *srcArrPtr=srcArr->getConstPointer();
9064   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9065   int it=start;
9066   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9067     {
9068       if(it>=0 && it<nbOfTuples)
9069         {
9070           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9071             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9072           else
9073             {
9074               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9075               throw INTERP_KERNEL::Exception(oss.str().c_str());
9076             }
9077         }
9078       else
9079         {
9080           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9081           throw INTERP_KERNEL::Exception(oss.str().c_str());
9082         }
9083     }
9084 }
9085
9086 /*!
9087  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9088  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9089  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9090  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9091  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9092  * 
9093  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9094  */
9095 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9096 {
9097   checkFullyDefined();
9098   int mdim=getMeshDimension();
9099   int spaceDim=getSpaceDimension();
9100   if(mdim!=spaceDim)
9101     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9102   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9103   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9104   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9105   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9106   ret->setCoords(getCoords());
9107   ret->allocateCells((int)partition.size());
9108   //
9109   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9110     {
9111       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9113       switch(mdim)
9114         {
9115         case 2:
9116           cell=tmp->buildUnionOf2DMesh();
9117           break;
9118         case 3:
9119           cell=tmp->buildUnionOf3DMesh();
9120           break;
9121         default:
9122           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9123         }
9124       
9125       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9126     }
9127   //
9128   ret->finishInsertingCells();
9129   return ret.retn();
9130 }
9131
9132 /*!
9133  * This method partitions \b this into contiguous zone.
9134  * This method only needs a well defined connectivity. Coordinates are not considered here.
9135  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9136  */
9137 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9138 {
9139   //#if 0
9140   int nbOfCellsCur=getNumberOfCells();
9141   std::vector<DataArrayInt *> ret;
9142   if(nbOfCellsCur<=0)
9143     return ret;
9144   DataArrayInt *neigh=0,*neighI=0;
9145   computeNeighborsOfCells(neigh,neighI);
9146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9147   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9148   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9149   int seed=0;
9150   while(seed<nbOfCellsCur)
9151     {
9152       int nbOfPeelPerformed=0;
9153       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9154       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9155     }
9156   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9157     ret.push_back((*it).retn());
9158   return ret;
9159   //#endif
9160 #if 0
9161   int nbOfCellsCur=getNumberOfCells();
9162   DataArrayInt *neigh=0,*neighI=0;
9163   computeNeighborsOfCells(neigh,neighI);
9164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9166   std::vector<DataArrayInt *> ret;
9167   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9168   while(nbOfCellsCur>0)
9169     {
9170       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9171       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9172       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9173       ret2.push_back(tmp2);  ret.push_back(tmp2);
9174       nbOfCellsCur=tmp3->getNumberOfTuples();
9175       if(nbOfCellsCur>0)
9176         {
9177           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9178           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9179           neighAuto=neigh;
9180           neighIAuto=neighI;
9181           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9182           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9183         }
9184     }
9185   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9186     (*it)->incrRef();
9187   return ret;
9188 #endif
9189 }
9190
9191 /*!
9192  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9193  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9194  *
9195  * \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.
9196  * \return a newly allocated DataArrayInt to be managed by the caller.
9197  * \throw In case of \a code has not the right format (typically of size 3*n)
9198  */
9199 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9200 {
9201   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9202   std::size_t nb=code.size()/3;
9203   if(code.size()%3!=0)
9204     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9205   ret->alloc((int)nb,2);
9206   int *retPtr=ret->getPointer();
9207   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9208     {
9209       retPtr[0]=code[3*i+2];
9210       retPtr[1]=code[3*i+2]+code[3*i+1];
9211     }
9212   return ret.retn();
9213 }
9214
9215 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9216                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9217 {
9218   if(mesh)
9219     {
9220       mesh->incrRef();
9221       _nb_cell=mesh->getNumberOfCells();
9222     }
9223 }
9224
9225 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9226 {
9227   if(_mesh)
9228     _mesh->decrRef();
9229   if(_own_cell)
9230     delete _cell;
9231 }
9232
9233 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9234                                                                                                                                _own_cell(false),_cell_id(bg-1),
9235                                                                                                                                _nb_cell(end)
9236 {
9237   if(mesh)
9238     mesh->incrRef();
9239 }
9240
9241 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9242 {
9243   _cell_id++;
9244   if(_cell_id<_nb_cell)
9245     {
9246       _cell->next();
9247       return _cell;
9248     }
9249   else
9250     return 0;
9251 }
9252
9253 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9254 {
9255   if(_mesh)
9256     _mesh->incrRef();
9257 }
9258
9259 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9260 {
9261   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9262 }
9263
9264 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9265 {
9266   if(_mesh)
9267     _mesh->decrRef();
9268 }
9269
9270 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9271                                                                                                                                                                   _itc(itc),
9272                                                                                                                                                                   _bg(bg),_end(end)
9273 {
9274   if(_mesh)
9275     _mesh->incrRef();
9276 }
9277
9278 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9279 {
9280   if(_mesh)
9281     _mesh->decrRef();
9282 }
9283
9284 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9285 {
9286   return _type;
9287 }
9288
9289 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9290 {
9291   return _end-_bg;
9292 }
9293
9294 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9295 {
9296   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9297 }
9298
9299 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9300 {
9301   if(mesh)
9302     {
9303       mesh->incrRef();
9304       _nb_cell=mesh->getNumberOfCells();
9305     }
9306 }
9307
9308 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9309 {
9310   if(_mesh)
9311     _mesh->decrRef();
9312   delete _cell;
9313 }
9314
9315 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9316 {
9317   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9318   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9319   if(_cell_id<_nb_cell)
9320     {
9321       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9322       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9323       int startId=_cell_id;
9324       _cell_id+=nbOfElems;
9325       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9326     }
9327   else
9328     return 0;
9329 }
9330
9331 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9332 {
9333   if(mesh)
9334     {
9335       _conn=mesh->getNodalConnectivity()->getPointer();
9336       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9337     }
9338 }
9339
9340 void MEDCouplingUMeshCell::next()
9341 {
9342   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9343     {
9344       _conn+=_conn_lgth;
9345       _conn_indx++;
9346     }
9347   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9348 }
9349
9350 std::string MEDCouplingUMeshCell::repr() const
9351 {
9352   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9353     {
9354       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9355       oss << " : ";
9356       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9357       return oss.str();
9358     }
9359   else
9360     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9361 }
9362
9363 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9364 {
9365   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9366     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9367   else
9368     return INTERP_KERNEL::NORM_ERROR;
9369 }
9370
9371 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9372 {
9373   lgth=_conn_lgth;
9374   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9375     return _conn;
9376   else
9377     return 0;
9378 }